package com.songlanyun.modules.rights.service.impl;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.songlanyun.common.enums.*;
import com.songlanyun.common.exception.RRException;
import com.songlanyun.common.kqUtils.InitQuery;
import com.songlanyun.common.kqUtils.InitReFund;
import com.songlanyun.common.kqUtils.quick.Bill99ConfigInfo;
import com.songlanyun.common.kqUtils.quick.BuildHttpsClient;
import com.songlanyun.common.lock.DistributedLock;
import com.songlanyun.common.supplychainapi.aftersale.ApiAfterSaleCommon;
import com.songlanyun.common.supplychainapi.aftersale.model.AfterSaleMailParam;
import com.songlanyun.common.supplychainapi.aftersale.model.BeforeCheck;
import com.songlanyun.common.supplychainapi.aftersale.model.BeforeCheckParam;
import com.songlanyun.common.utils.*;
import com.songlanyun.common.utils.custom.MathUtils;
import com.songlanyun.common.validator.ValidatorUtils;
import com.songlanyun.modules.exception.OrderException;
import com.songlanyun.modules.gains.service.ShopOrderGainsService;
import com.songlanyun.modules.integralrecord.entity.IntegralRecord;
import com.songlanyun.modules.integralrecord.service.IntegralRecordService;
import com.songlanyun.modules.memberbill.service.SaleRefillCardBillService;
import com.songlanyun.modules.order.entity.*;
import com.songlanyun.modules.order.model.vo.UserOrderRightsSlimStatisticsVo;
import com.songlanyun.modules.order.service.ChildOrderService;
import com.songlanyun.modules.order.service.OrderService;
import com.songlanyun.modules.order.service.SaleServiceOrderContactsService;
import com.songlanyun.modules.payorder.entity.PayOrder;
import com.songlanyun.modules.payorder.entity.SaleOrderReductionRecord;
import com.songlanyun.modules.payorder.model.dto.KqBankCardQueryDTO;
import com.songlanyun.modules.payorder.service.SaleOrderReductionRecordService;
import com.songlanyun.modules.payrefund.entity.PayRefundOrder;
import com.songlanyun.modules.payrefund.service.PayRefundOrderService;
import com.songlanyun.modules.rights.dao.RightsOrderDao;
import com.songlanyun.modules.rights.entity.RightsChildOrder;
import com.songlanyun.modules.rights.entity.RightsOrder;
import com.songlanyun.modules.rights.entity.RightsOrderOperateRecord;
import com.songlanyun.modules.rights.entity.RightsOrderShipRecord;
import com.songlanyun.modules.rights.model.dto.*;
import com.songlanyun.modules.rights.model.vo.RightsMoneyVo;
import com.songlanyun.modules.rights.service.RightsChildOrderService;
import com.songlanyun.modules.rights.service.RightsOrderOperateRecordService;
import com.songlanyun.modules.rights.service.RightsOrderService;
import com.songlanyun.modules.rights.service.RightsOrderShipRecordService;
import com.songlanyun.modules.saleconfig.entity.SaleConfig;
import com.songlanyun.modules.saleconfig.service.SaleConfigService;
import com.songlanyun.modules.singlegoods.model.OrderStockTo;
import com.songlanyun.modules.singlegoods.service.ProductSingleGoodsService;
import com.songlanyun.pay.bean.RefundModel;
import com.songlanyun.pay.common.util.CalculateUtil;
import com.songlanyun.pay.service.PayService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;


@Service("saleRightsOrderService")
@Slf4j
public class RightsOrderServiceImpl extends ServiceImpl<RightsOrderDao, RightsOrder> implements RightsOrderService {


    @Autowired
    private RightsChildOrderService rightsChildOrderService;

    @Autowired
    private OrderService orderService;

    @Autowired
    private ChildOrderService childOrderService;

    @Autowired
    private RightsOrderOperateRecordService recordService;

    @Autowired
    private RightsOrderShipRecordService shipRecordService;

    @Autowired
    private SaleRefillCardBillService saleRefillCardBillService;

    @Autowired
    private PayRefundOrderService payRefundOrderService;

    @Autowired
    private ProductSingleGoodsService productSingleGoodsService;

    @Autowired
    private SaleConfigService saleConfigService;

    @Autowired
    private ShopOrderGainsService shopOrderGainsService;
    @Autowired
    private RightsOrderShipRecordService rightsOrderShipRecordService;


    @Autowired
    private IntegralRecordService integralRecordService;

    @Autowired
    private SaleServiceOrderContactsService saleServiceOrderContactsService;


    @Autowired
    @Qualifier("payService2")
    private PayService payService;

    @Autowired
    private ApiAfterSaleCommon apiAfterSaleCommon;

    @Autowired
    private HouniaoApiUtil houniaoApiUtil;

    @Autowired
    private BuildHttpsClient buildHttpsClient;

    @Autowired
    private SaleOrderReductionRecordService saleOrderReductionRecordService;


    @Override
    public RightsOrder create(RightsOrder entity) {
//        ValidatorUtils.validateEntity(entity);
        this.baseMapper.insert(entity);
        return entity;
    }

    @Override
    public RightsOrder modify(RightsOrder entity) {
        ValidatorUtils.validateEntity(entity);
        this.baseMapper.updateById(entity);
        return entity;
    }

    @Override
    public void remove(Long id) {

    }

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        String client = MapUtil.getStr(params, "client");
        Integer areaFeature = MapUtil.getInt(params, "area_feature");
        Integer[] areaFeatures = new Integer[]{0,1,2};

        IPage<RightsOrder> page = this.page(
                new Query<RightsOrder>().getPage(params),
                new LambdaQueryWrapper<RightsOrder>()
                        .eq(MapUtil.getLong(params, "shop_id") != null, RightsOrder::getShopId, MapUtil.getLong(params, "shop_id"))
                        .like(StringUtils.isNotBlank(MapUtil.getStr(params, "shop_name")), RightsOrder::getShopName, MapUtil.getStr(params, "shop_name"))
                        .eq(MapUtil.getLong(params, "user_id") != null, RightsOrder::getUserId, MapUtil.getLong(params, "user_id"))
                        .in(areaFeature!=null && areaFeature == 0,RightsOrder::getAreaFeature, Arrays.asList(areaFeatures))
                        .eq(areaFeature!=null && areaFeature > 0,RightsOrder::getAreaFeature, areaFeature)
                        .eq(MapUtil.getInt(params, "rights_type") != null, RightsOrder::getRightsType, MapUtil.getLong(params, "rights_type"))
                        .like(StringUtils.isNotBlank(MapUtil.getStr(params, "order_creator_mobile")), RightsOrder::getMobile, MapUtil.getStr(params, "order_creator_mobile"))
                        .like(StringUtils.isNotBlank(MapUtil.getStr(params, "order_code")), RightsOrder::getOrderCode, MapUtil.getStr(params, "order_code"))
                        .like(StringUtils.isNotBlank(MapUtil.getStr(params, "pay_refund_code")), RightsOrder::getPayRefundCode, MapUtil.getStr(params, "pay_refund_code"))
                        .like(StringUtils.isNotBlank(MapUtil.getStr(params, "rights_code")), RightsOrder::getRightsCode, MapUtil.getStr(params, "rights_code"))
                        .and(StringUtils.isNotBlank(MapUtil.getStr(params, "receiver_mobile")), param -> {
                            param.like(RightsOrder::getMobile, MapUtil.getStr(params, "receiver_mobile")).or().like(RightsOrder::getReceiverMobile, MapUtil.getStr(params, "receiver_mobile"));
                        }).eq(MapUtil.getInt(params, "refund_status") != null, RightsOrder::getRightsRefundStatus, MapUtil.getInt(params, "refund_status"))
                        .eq(MapUtil.getInt(params, "operate_status") != null, RightsOrder::getRightsOperateStatus, MapUtil.getInt(params, "operate_status"))
                        .eq(MapUtil.getInt(params, "order_type") != null, RightsOrder::getOrderType, MapUtil.getInt(params, "order_type"))
                        .eq(MapUtil.getInt(params, "third") != null && MapUtil.getInt(params, "third")>-1, RightsOrder::getThird, MapUtil.getInt(params, "third"))
                        //.eq(StringUtils.isNotBlank(client) && client.equals("applet"), RightsOrder::getRefundPoint, 0)
                        .orderByDesc(RightsOrder::getCreateTime)
        );
        page.getRecords().forEach(o ->
        {
            o.loadRightsChildOrders();
            Order order = o.loadOrder();
            order.loadShop();
        });
        return new PageUtils(page);
    }

    /**
     * 查看主订单的维权单
     *
     * @param userId
     * @param orderId
     * @param tw
     * @return
     */
    @Override
    public RightsOrder loadMainRightsOrder(Long userId, Long orderId, boolean tw) {
        RightsOrder one = this.getOne(new LambdaQueryWrapper<RightsOrder>()
                .eq(RightsOrder::getUserId, userId)
                .eq(RightsOrder::getOrderId, orderId)
                .eq(RightsOrder::getIsAllRights, true)
                .eq(RightsOrder::getValid, true)
                .last("limit 1"));
        if (one == null && tw) {
            throw new RRException(OrderException.RIGHTS_ORDER_NOT_EXISTS);
        }
        return one;
    }

    /**
     * 查询只有子订单的维权单
     *
     * @param userId
     * @param orderId
     * @param childOrderId
     * @param tw
     * @return
     */
    @Override
    public RightsOrder loadChildRightsOrder(Long userId, Long orderId, Long childOrderId, boolean tw) {
        RightsOrder one = this.getOne(new LambdaQueryWrapper<RightsOrder>()
                .eq(RightsOrder::getUserId, userId)
                .eq(RightsOrder::getOrderId, orderId)
                .eq(RightsOrder::getIsAllRights, false)
                .eq(RightsOrder::getValid, true)
                .last("limit 1"));

        if (one == null) {
            if (tw) {
                throw new RRException(OrderException.RIGHTS_ORDER_NOT_EXISTS);
            }
            return null;

        } else {
            RightsChildOrder rightsChildOrder = rightsChildOrderService.loadChildRightsOrder(one.getId(), orderId, childOrderId, tw);
            if (rightsChildOrder == null) {
                if (tw) {
                    throw new RRException(OrderException.RIGHTS_CHILD_ORDER_NOT_EXISTS);
                } else {
                    return null;
                }

            }
            return one;
        }
    }

    /**
     * 查询维权订单
     *
     * @param userId
     * @param id
     * @param tw
     * @return
     */
    @Override
    public RightsOrder loadByUserAndId(Long userId, Long id, boolean tw) {
        RightsOrder one = this.getOne(new LambdaQueryWrapper<RightsOrder>()
                .eq(RightsOrder::getUserId, userId)
                .eq(RightsOrder::getId, id)
                .last("limit 1"));

        if (one == null && tw) {
            throw new RRException(OrderException.RIGHTS_ORDER_NOT_EXISTS);
        }

        return one;
    }


    /**
     * /**
     * 退货流程：
     * 退货申请➡商家同意➡买家发货➡商家确认收货➡打款
     * 退货申请➡商家不同意
     * <p>
     * 退货条件：
     * 必须后收货后才能退货。
     * <p>
     * 退款流程：
     * 退款申请➡商家同意➡打款
     * 退款申请➡商家不同意
     * <p>
     * 退款条件：
     * 支付后即可申请退款。未发货只能全部退款，待收货不能退款，收货可退款。
     * <p>
     * 打款：打款由商家提交退款申请，从平台微信商户/支付宝商户中退相应金额的款项，同时扣除商家所得。
     * <p>
     * 主订单申请维权
     *
     * @param dto
     * @return
     */
    @Override
    @Transactional
    public RightsOrder applyOrder(ApplyOrderRightsDTO dto) {
        Order order = orderService.loadByUserIdAndId(dto.getUserId(), dto.getOrderId(), true);
        dto.setRightsOperatePerson(RightsOrderConstant.RightsOperatePerson.USER.getCode());
        if (dto.getRightsType() == 0) {
            throw new RRException(OrderException.RIGHTS_TYPE_ERROR);
        }
        //没有支付成功不能申请退款
        if (!OrderConstant.PaymentStatus.SUCCESS.equals(order.getPaymentStatus())) {
            throw new RRException(OrderException.NOT_PAY_NOT_RIGHTS);
        }
        if (OrderConstant.OrderType.SALE_ORDER.equals(order.getOrderType())) {

            //已发货没有收货的订单不能申请维权
            if (OrderConstant.ShipStatus.ALREADY_SHIP.equals(order.getShipStatus())
                    && OrderConstant.ReceiptStatus.NO.equals(order.getReceiptStatus())) {

                throw new RRException(OrderException.SHIP_NOT_RECEIPT);
            }
            if (dto.getRightsType().equals(OrderConstant.RightsType.RETURN.getCode())) {
                if (!OrderConstant.ReceiptStatus.COMPLETE.equals(order.getReceiptStatus())) {
                    throw new RRException(OrderException.SHIP_NOT_RECEIPT);
                }
            }
        }


        //订单已关闭
        if (order.getEnd()) {
            throw new RRException(OrderException.ORDER_END);
        }


        //已存在主维权单不参重复
        if (this.getCountRightsOrder(order.getId(), true) > 0) {
            throw new RRException(OrderException.MAIN_ORDER_RIGHTS_REPEAT);
        }

        //如果存在子维权订单
        if (this.getCountRightsOrder(order.getId(), false) > 0) {
            throw new RRException(OrderException.MAIN_ORDER_RIGHTS_REPEAT);
        }


        BigDecimal orderMoney = order.getTotalAmount();
        BigDecimal orderPoint = order.getTotalPoint();

        if (orderMoney.compareTo(BigDecimal.ZERO) == 0 && orderPoint.compareTo(BigDecimal.ZERO) == 0 && dto.getRightsType() == 1) {
            throw new RRException(OrderException.REFUND_MONEY_ZERO);
        }

        //申请的维权金额不能超过订单实际金额
        if (OrderConstant.ShipStatus.ALREADY_SHIP.equals(order.getShipStatus())) {
            //如果已发货，运费不能退
            if (!order.getExchange()) {
                orderMoney = MathUtils.subtract(orderMoney, order.getRealFreight());
            } else {
                orderMoney = BigDecimal.ZERO;
            }
        }

        if (dto.getRefundMoney().compareTo(orderMoney) > 0) {
            throw new RRException(String.format(OrderException.OVERFLOW_ORDER_FACT_COST.getMsg(), orderMoney.toString()), OrderException.OVERFLOW_ORDER_FACT_COST.getCode());
        }

        /**
         * 申请退还的积分不能超过订单实际使用积分
         */
        if (dto.getRefundPoint().compareTo(orderPoint) >0) {
            throw new RRException(String.format(OrderException.OVERFLOW_ORDER_FACT_POINT.getMsg(), order.getTotalPoint()), OrderException.OVERFLOW_ORDER_FACT_POINT.getCode());

        }


        /**
         * 第一步创建维权订单
         */
        RightsOrder rightsOrder = build(order, dto);
        rightsOrder.setAreaFeature(order.getAreaFeature());
        rightsOrder.setRefundNum(order.getGoodsNumber());
        rightsOrder.setRefundPoint(order.getTotalPoint());
        this.create(rightsOrder);
        //更新主订单的维权状态
        order.setRightsStatus(OrderConstant.RightsStatus.BEING);
        order.setRightsType(rightsOrder.getRightsType());
        orderService.modify(order);
        /**
         * 第二步创建维权订单明细
         */
        List<ChildOrder> childOrderList = order.getChildOrderList(true);
        for (ChildOrder childOrder : childOrderList) {
            BigDecimal refundMoney = BigDecimal.ZERO;
            BigDecimal refundPoint = BigDecimal.ZERO;
            if (orderMoney.compareTo(BigDecimal.ZERO) > 0) {
//                refundMoney = MathUtils.subtractMulti(childOrder.getTotalRealPrice(),
//                        childOrder.getFirstOrderReduced(),
//                        childOrder.getShopCouponSharing(),
//                        childOrder.getPlatformCouponSharing(),
//                        childOrder.getPlatformPointZxSharing());

                refundMoney = MathUtils.setScale((rightsOrder.getRefundMoney().doubleValue() * childOrder.getTotalRealPrice().doubleValue()) / order.getGoodsAmount().doubleValue());
            }
            if (orderPoint.compareTo(BigDecimal.ZERO) > 0) {
                // refundPoint = childOrder.getTotalPoint();
               refundPoint = MathUtils.divide(MathUtils.multiply(rightsOrder.getRefundPoint(),childOrder.getTotalPoint()),order.getTotalPoint());
            }

            RightsChildOrder rightsChild = build(rightsOrder, childOrder, childOrder.getNumber(), refundMoney, refundPoint);
            rightsChildOrderService.create(rightsChild);

            /**
             * 更新子订单的维权状态
             */
            childOrder.setRightsStatus(OrderConstant.RightsStatus.BEING);
            childOrder.setRightsType(rightsOrder.getRightsType());
            childOrderService.modify(childOrder);
        }

        /**
         * 第三步创建维权订单操作日志
         */
        createRecord(rightsOrder.getId(), rightsOrder.getRightsOperateStatus(), rightsOrder.getReason(), rightsOrder.getVoucherImages(), RightsOrderConstant.RightsOperatePerson.USER);

        /**
         * 第三步，如果此订单是维权订单，则需要将维权数据推送到点三方系统中
         */
        if(order.getThird()) {
            ChildOrder childOrder = childOrderService.loadByOrderAndChildId(order.getId(), dto.getChildOrderId(), true);
            JSONObject req = new JSONObject();
            req.put("post_type", String.valueOf(dto.getThirdPostType()));
            req.put("refund_reason_id", String.valueOf(dto.getThirdRefundReasonId()));
            req.put("order_no", String.valueOf(childOrder.getThirdOrderNo()));
            req.put("order_id", "0");
            req.put("source_sale_sn", String.valueOf(rightsOrder.getRightsCode()));
            req.put("num", String.valueOf(childOrder.getNumber()));
            req.put("gather_money", String.valueOf(childOrder.getTotalRealPrice()));

            String refund_description = String.valueOf(dto.getReason());
            if(StringUtils.isNotBlank(refund_description)){
                req.put("refund_description", refund_description);
            }

            String addenda_img = joinImgUrl(dto.getThirdAddendaImg());
            if(StringUtils.isNotBlank(addenda_img)){
                req.put("addenda_img", addenda_img);
            }

            String express_img = joinImgUrl(dto.getThirdExpressImg());
            if(StringUtils.isNotBlank(express_img)){
                req.put("express_img", express_img);
            }

            String package_img = joinImgUrl(dto.getThirdPackageImg());
            if(StringUtils.isNotBlank(package_img)){
                req.put("package_img", package_img);
            }

            String product_img = joinImgUrl(dto.getThirdProductImg());
            if(StringUtils.isNotBlank(product_img)){
                req.put("product_img", product_img);
            }

            String defect_product_img = joinImgUrl(dto.getThirdDefectProductImg());
            if(StringUtils.isNotBlank(defect_product_img)){
                req.put("defect_product_img", defect_product_img);
            }

            String product_shelf_life_img = joinImgUrl(dto.getThirdProductShelfLifeImg());
            if(StringUtils.isNotBlank(product_shelf_life_img)){
                req.put("product_shelf_life_img", product_shelf_life_img);
            }

            try {
                JSONObject js = houniaoApiUtil.client(req, HouniaoConstant.AFTER_SALE_APPLY.getUrl());
                if(200 != js.getIntValue("code")){
                    throw new RRException(js.getString("msg"), js.getIntValue("code"));
                }
            } catch (Exception ex) {
                throw new RuntimeException(ex.getLocalizedMessage());
            }
        }



        return rightsOrder;
    }


    private RightsOrder systemCreateRightsOrder(Order order, RightsOrderConstant.RightsOperatePerson rightsOperatePerson) {
        RightsOrder rightsOrder = new RightsOrder();
        rightsOrder.setRightsCode(OrderGen.generateOrderNo());
        rightsOrder.setRefundMoney(order.getTotalAmount());
        rightsOrder.setRefundPoint(order.getTotalPoint());
        rightsOrder.setReason(RightsOrderConstant.RightsOperatePerson.SYSTEM.equals(rightsOperatePerson) ? "自动退款" : "商家主动退款");
        rightsOrder.setCaption("");
        rightsOrder.setVoucherImages(new ArrayList<>());
        rightsOrder.setRightsCargoStatus(RightsOrderConstant.RightsCargoStatus.NOT);
        rightsOrder.setRightsType(OrderConstant.RightsType.REFUND);
        rightsOrder.setShopId(order.getShopId());
        rightsOrder.setShopName(order.getShopName());
        rightsOrder.setOrderId(order.getId());
        rightsOrder.setOrderCode(order.getOrderCode());
        rightsOrder.setPayMode(order.getPayMode());
        rightsOrder.setUserId(order.getUserId());
        rightsOrder.setMobile(order.getMobile());
        if (OrderConstant.ShipmentMode.EXPRESS.equals(order.getShipmentMode())) {
            OrderReceipt orderReceipt = order.loadOrderReceipt();
            rightsOrder.setReceiver(orderReceipt.getReceiver());
            rightsOrder.setReceiverMobile(orderReceipt.getMobile());
        }

        if (OrderConstant.ShipmentMode.PICK_UP.equals(order.getShipmentMode())) {
            OrderSelfTake orderSelfTake = order.loadOrderSelfTake();
            rightsOrder.setReceiver(orderSelfTake.getReceiver());
            rightsOrder.setReceiverMobile(orderSelfTake.getMobile());
        }


        rightsOrder.setPayRefundId(0L);
        rightsOrder.setPayRefundCode("");
        rightsOrder.setThirdRefundCode("");
        rightsOrder.setLastAgreeTime(0L);
        rightsOrder.setRefundNum(order.getGoodsNumber());
        rightsOrder.setRightsOperatePerson(rightsOperatePerson);
        rightsOrder.setRefundPoint(order.getTotalPoint());
        rightsOrder.setOrderType(order.getOrderType());
        this.create(rightsOrder);
        return rightsOrder;
    }

    @Override
    public PayRefundOrder systemAutoRefund(Order order, RightsOrderConstant.RightsOperatePerson rightsOperatePerson) {
        //没有支付成功不能申请退款
        if (!OrderConstant.PaymentStatus.SUCCESS.equals(order.getPaymentStatus())) {
            return null;
        }
        //已存在主维权单
        if (this.getCountRightsOrder(order.getId(), true) > 0) {
            return null;
        }

        /**
         * 第一步创建维权订单
         */
        //生成维权订单==============================================================
        RightsOrder rightsOrder = systemCreateRightsOrder(order, rightsOperatePerson);

        //更新主订单的维权状态
        order.setRightsStatus(OrderConstant.RightsStatus.BEING);
        order.setRightsType(rightsOrder.getRightsType());
        orderService.modify(order);
        /**
         * 第二步创建维权订单明细
         */
        List<ChildOrder> childOrderList = order.getChildOrderList(true);
        for (ChildOrder childOrder : childOrderList) {
            BigDecimal refundMoney = BigDecimal.ZERO;
            if (order.getGoodsAmount().compareTo(BigDecimal.ZERO) > 0) {
                refundMoney = MathUtils.setScale((rightsOrder.getRefundMoney().doubleValue() * childOrder.getTotalRealPrice().doubleValue()) / order.getGoodsAmount().doubleValue());
            }
            RightsChildOrder rightsChild = build(rightsOrder, childOrder, childOrder.getNumber(), refundMoney, childOrder.getTotalPoint());
            rightsChildOrderService.create(rightsChild);
            /**
             * 更新子订单的维权状态
             */
            childOrder.setRightsStatus(OrderConstant.RightsStatus.BEING);
            childOrder.setRightsType(rightsOrder.getRightsType());
            childOrderService.modify(childOrder);
        }

        /**
         * 第三步创建维权订单操作日志
         */
        createRecord(rightsOrder.getId(), rightsOrder.getRightsOperateStatus(), rightsOrder.getReason(), rightsOrder.getVoucherImages(), rightsOperatePerson);


        /**
         * 第四步修改维权单的状态成为已同意
         */
        rightsOrder.setRightsOperateStatus(RightsOrderConstant.RightsOperateStatus.AGREE);
        this.modify(rightsOrder);

        /**
         * 第五步创建维权订单操作日志
         */
        createRecord(rightsOrder.getId(), rightsOrder.getRightsOperateStatus(), "", new ArrayList<>(), rightsOperatePerson);

        /**
         * 第六步发起退款
         */
        PayRefundOrder refund = refund(rightsOrder);
        return refund;
    }

    @Transactional
    @Override
    public PayRefundOrder shopServiceOrderRefund(Long shopId, ApplyOrderRightsDTO dto) {
        Order order = orderService.loadByShopIdAndId(shopId, dto.getOrderId(), true);
        dto.setRightsType(1);
        dto.setRightsOperatePerson(2);
        dto.setRefundPoint(BigDecimal.ZERO);
        dto.setRightsCargoStatus(0);
        dto.setVoucherImages(new ArrayList<>());
        dto.setReason("商家主动退款");
        dto.setUserId(order.getUserId());
        if (dto.getRightsType() == 0) {
            throw new RRException(OrderException.RIGHTS_TYPE_ERROR);
        }
        //没有支付成功不能申请退款
        if (!OrderConstant.PaymentStatus.SUCCESS.equals(order.getPaymentStatus())) {
            throw new RRException(OrderException.NOT_PAY_NOT_RIGHTS);
        }
        if (!OrderConstant.OrderType.SERVICE_ORDER.equals(order.getOrderType())) {

            throw new RRException("不是服务订单");
        }

        //订单已关闭
        if (order.getEnd()) {
            throw new RRException(OrderException.ORDER_END);
        }


        //已存在主维权单不参重复
        if (this.getCountRightsOrder(order.getId(), true) > 0) {
            throw new RRException(OrderException.MAIN_ORDER_RIGHTS_REPEAT);
        }

        //如果存在子维权订单
        if (this.getCountRightsOrder(order.getId(), false) > 0) {
            throw new RRException(OrderException.MAIN_ORDER_RIGHTS_REPEAT);
        }


        BigDecimal orderMoney = order.getTotalAmount();


        if (orderMoney.compareTo(BigDecimal.ZERO) == 0 && order.getTotalPoint().compareTo(BigDecimal.ZERO) == 0 && dto.getRightsType() == 1) {
            throw new RRException(OrderException.REFUND_MONEY_ZERO);
        }

        if (dto.getRefundMoney().compareTo(orderMoney) > 0) {
            throw new RRException(String.format(OrderException.OVERFLOW_ORDER_FACT_COST.getMsg(), orderMoney.toString()), OrderException.OVERFLOW_ORDER_FACT_COST.getCode());
        }

        /**
         * 申请退还的积分不能超过订单实际使用积分
         */
        if (dto.getRefundPoint().compareTo(order.getTotalPoint())>0 ) {
            throw new RRException(String.format(OrderException.OVERFLOW_ORDER_FACT_POINT.getMsg(), order.getTotalPoint()), OrderException.OVERFLOW_ORDER_FACT_POINT.getCode());

        }


        /**
         * 第一步创建维权订单
         */
        RightsOrder rightsOrder = build(order, dto);
        rightsOrder.setRefundNum(order.getGoodsNumber());
        this.create(rightsOrder);
        //更新主订单的维权状态
        order.setRightsStatus(OrderConstant.RightsStatus.BEING);
        order.setRightsType(rightsOrder.getRightsType());
        orderService.modify(order);
        /**
         * 第二步创建维权订单明细
         */
        List<ChildOrder> childOrderList = order.getChildOrderList(true);
        for (ChildOrder childOrder : childOrderList) {
            BigDecimal refundMoney = BigDecimal.ZERO;
            BigDecimal refundPoint = BigDecimal.ZERO;
            if (!order.getExchange()) {
                if (order.getGoodsAmount().compareTo(BigDecimal.ZERO) > 0) {
                    refundMoney = MathUtils.setScale((rightsOrder.getRefundMoney().doubleValue() * childOrder.getTotalRealPrice().doubleValue()) / order.getGoodsAmount().doubleValue());
                }
            } else {
                if (order.getTotalPoint().compareTo(BigDecimal.ZERO) > 0) {
                    refundPoint = MathUtils.divide(MathUtils.multiply(rightsOrder.getRefundPoint(),childOrder.getTotalPoint()),order.getTotalPoint());
                }
            }
            RightsChildOrder rightsChild = build(rightsOrder, childOrder, childOrder.getNumber(), refundMoney, refundPoint);
            rightsChildOrderService.create(rightsChild);

            /**
             * 更新子订单的维权状态
             */
            childOrder.setRightsStatus(OrderConstant.RightsStatus.BEING);
            childOrder.setRightsType(rightsOrder.getRightsType());
            childOrderService.modify(childOrder);
        }

        /**
         * 第三步创建维权订单操作日志
         */
        createRecord(rightsOrder.getId(), rightsOrder.getRightsOperateStatus(), rightsOrder.getReason(), rightsOrder.getVoucherImages(), RightsOrderConstant.RightsOperatePerson.USER);
        /**
         * 第四步修改维权单的状态成为已同意
         */
        rightsOrder.setRightsOperateStatus(RightsOrderConstant.RightsOperateStatus.AGREE);
        this.modify(rightsOrder);

        /**
         * 第五步创建维权订单操作日志
         */
        createRecord(rightsOrder.getId(), rightsOrder.getRightsOperateStatus(), "", new ArrayList<>(), rightsOrder.getRightsOperatePerson());

        /**
         * 第六步发起退款
         */
        PayRefundOrder refund = refund(rightsOrder);
        return refund;
    }

    /**
     * 商家发起自动退款
     *
     * @param shopId
     * @param orderId
     */
    @Transactional
    @Override
    public PayRefundOrder shopLaunchRefund(Long shopId, Long orderId) {
        Order order = orderService.loadByShopIdAndId(shopId, orderId, true);

        if (!OrderConstant.OrderType.SALE_ORDER.equals(order.getOrderType())) {
            throw new RRException("只支持普通订单的全额退款");
        }
        PayRefundOrder payRefundOrder = systemAutoRefund(order, RightsOrderConstant.RightsOperatePerson.SHOP);
        return payRefundOrder;
    }


    /**
     * 获得主订单维权可以最多可以退多少钱
     *
     * @param userId
     * @param orderId
     * @return
     */
    @Override
    public RightsMoneyVo getMoneyByMainRights(Long userId, Long orderId) {
        Order order = orderService.loadByUserIdAndId(userId, orderId, true);
        BigDecimal orderMoney = order.getTotalAmount();
        BigDecimal orderPoint = order.getTotalPoint();
        //申请的维权金额不能超过订单实际金额
        if (OrderConstant.ShipStatus.ALREADY_SHIP.equals(order.getShipStatus())) {
            //如果已发货，运费不能退
            orderMoney = MathUtils.subtract(orderMoney, order.getRealFreight());
        }
        RightsMoneyVo rightsMoneyVo = new RightsMoneyVo();
        rightsMoneyVo.setGoodsNum(order.getGoodsNumber());
        rightsMoneyVo.setAbleRefundMoney(orderMoney);
        rightsMoneyVo.setAbleRefundPoint(orderPoint);

        return rightsMoneyVo;
    }

    /**
     * 获得子订单维权可以最多可以退多少钱
     *
     * @return
     */
    @Override
    public RightsMoneyVo getMoneyByChildRights(ApplyOrderRightsDTO dto) {

        Order order = orderService.loadByUserIdAndId(dto.getUserId(), dto.getOrderId(), true);
        ChildOrder childOrder = childOrderService.loadByOrderAndChildId(order.getId(), dto.getChildOrderId(), true);
        if (dto.getRefundNum() == null) {
            dto.setRefundNum(childOrder.getNumber());
        }
        //维权订单数量超出购买商品数量
        if (dto.getRefundNum() > childOrder.getNumber()) {
            throw new RRException(OrderException.RIGHTS_GOODS_NUM_OVERFLOW);
        }
        BigDecimal orderMoney = BigDecimal.ZERO;
        if (!order.getExchange()) {
            //申请的维权金额不能超过订单实际金额

            orderMoney = MathUtils.multiply(childOrder.getRealPrice(), new BigDecimal(dto.getRefundNum()));
            if (childOrder.getNumber().equals(dto.getRefundNum())) {
                orderMoney = MathUtils.subtractMulti(orderMoney, childOrder.getFirstOrderReduced(),childOrder.getShopCouponSharing(),childOrder.getPlatformCouponSharing(),childOrder.getPlatformPointZxSharing());
            } else {
                double v = childOrder.getFirstOrderReduced().doubleValue() * dto.getRefundNum() / childOrder.getNumber();
                double s = childOrder.getShopCouponSharing().doubleValue() * dto.getRefundNum() / childOrder.getNumber();
                double p = childOrder.getPlatformCouponSharing().doubleValue() * dto.getRefundNum() / childOrder.getNumber();
                double z = childOrder.getPlatformPointZxSharing().doubleValue() * dto.getRefundNum() / childOrder.getNumber();
                orderMoney = MathUtils.subtractMulti(orderMoney, MathUtils.setScale(v),MathUtils.setScale(s),MathUtils.setScale(p),MathUtils.setScale(z));
            }
        }

        BigDecimal orderPoint = MathUtils.multiply(childOrder.getExchangePoint(),new BigDecimal(dto.getRefundNum()));
        RightsMoneyVo rightsMoneyVo = new RightsMoneyVo();
        rightsMoneyVo.setGoodsNum(dto.getRefundNum());
        rightsMoneyVo.setAbleRefundMoney(orderMoney);
        //候鸟运费
        if (childOrder.getThird() && childOrder.getShopId() == 30){
            BigDecimal realFreight = order.getRealFreight();
            rightsMoneyVo.setAbleRefundMoney(orderMoney.add(realFreight));
        }
        rightsMoneyVo.setAbleRefundPoint(orderPoint);

        return rightsMoneyVo;
    }

    /**
     * 退货物流跟踪
     *
     * @param rightsId
     * @return
     */
    @Override
    public RightsOrderShipRecord expressSelect(Long rightsId) {
        RightsOrder rightsOrder = this.getById(rightsId);
        if (!OrderConstant.RightsType.RETURN.equals(rightsOrder.getRightsType())) {
            return null;
        }
        RightsOrderShipRecord rightsOrderShipRecord = rightsOrderShipRecordService.loadByRightsId(rightsId, false);
        if (rightsOrderShipRecord == null) {
            return null;
        }


        if (rightsOrderShipRecord.isAbleSelect()) {
//            String result = orderService.queryExpressExpNo(rightsOrderShipRecord.getLogisticCode());
            String result = orderService.queryExpressExpNo(rightsOrderShipRecord.getLogisticCode(), rightsOrder.getMobile());
            rightsOrderShipRecord.setQueryResult(result);
            rightsOrderShipRecord.setLastQueryTime(new Date());
            rightsOrderShipRecordService.modify(rightsOrderShipRecord);
        }
        return rightsOrderShipRecord;

    }

    @Override
    public UserOrderRightsSlimStatisticsVo loadOrderRightsSlimStatistics(Long shopId, Long userId) {
        return this.baseMapper.loadOrderRightsSlimStatistics(shopId, userId);
    }

    @Override
    public Integer loadRightsOrderNum(Long shopId, Integer status) {
        return this.baseMapper.loadRightsOrderNum(shopId, status);
    }

    @Override
    public RightsOrder loadByThirdRightsId(Long afterSaleId) {
        RightsOrder one = this.getOne(new LambdaQueryWrapper<RightsOrder>()
                .eq(RightsOrder::getThirdRightsId, afterSaleId)
                .eq(RightsOrder::getThird, true)
                .last("limit 1"));

        return one;
    }


    /**
     * 退货流程：
     * 退货申请➡商家同意➡买家发货➡商家确认收货➡打款
     * 退货申请➡商家不同意
     * <p>
     * 退货条件：
     * 必须后收货后才能退货。
     * <p>
     * 退款流程：
     * 退款申请➡商家同意➡打款
     * 退款申请➡商家不同意
     * <p>
     * 退款条件：
     * 支付后即可申请退款。未发货只能全部退款，待收货不能退款，收货可退款。
     * <p>
     * 打款：打款由商家提交退款申请，从平台微信商户/支付宝商户中退相应金额的款项，同时扣除商家所得。
     * <p>
     * 子订单申请维权
     */
    @Transactional
    @Override
    public RightsOrder applyChildOrder(ApplyOrderRightsDTO dto) {
        Order order = orderService.loadByUserIdAndId(dto.getUserId(), dto.getOrderId(), true);
        ChildOrder childOrder = childOrderService.loadByOrderAndChildId(order.getId(), dto.getChildOrderId(), true);
        //没有选择一种维权方式
        if (dto.getRightsType() == 0) {
            throw new RRException(OrderException.RIGHTS_TYPE_ERROR);
        }

        //没有支付成功不能申请退款
        if (!OrderConstant.PaymentStatus.SUCCESS.equals(order.getPaymentStatus())) {
            throw new RRException(OrderException.NOT_PAY_NOT_RIGHTS);
        }
        //子订单已关闭
        if (childOrder.getEnd()) {
            throw new RRException(OrderException.ORDER_END);
        }
        //子订单存在维权
        if (!OrderConstant.RightsStatus.NO.equals(childOrder.getRightsStatus())) {
            throw new RRException(OrderException.CHILD_ORDER_RIGHTS_REPEAT);
        }

        //已发货没有收货的子订单不能申请子订单维权
        if (childOrder.getShipStatus().getCode()>0 && !OrderConstant.ReceiptStatus.COMPLETE.equals(childOrder.getReceiptStatus())) {
            throw new RRException(OrderException.LOGISTICS_CHILD_NOT_RIGHTS);
        }

        //没有发货不能申请退货退款
        if (dto.getRightsType().equals(2) && childOrder.getShipStatus().equals(OrderConstant.ShipStatus.NO_SHIP)) {
            throw new RRException(OrderException.NOT_RECEIPT_APPLY_CHILD);
        }


        //维权订单数量超出购买商品数量
        if (dto.getRefundNum() > childOrder.getNumber()) {
            throw new RRException(OrderException.RIGHTS_GOODS_NUM_OVERFLOW);
        }

        //已存在主维权单
        if (this.getCountRightsOrder(order.getId(), true) > 0) {
            throw new RRException(OrderException.MAIN_ORDER_RIGHTS_REPEAT);
        }
        //零元订单不能申请退款
        if (dto.getRefundMoney().compareTo(BigDecimal.ZERO) == 0 && childOrder.getTotalPoint().compareTo(BigDecimal.ZERO) == 0 && dto.getRightsType() == 1) {
            throw new RRException(OrderException.REFUND_MONEY_ZERO);
        }

        //申请的维权金额不能超过订单实际金额
        BigDecimal orderMoney = BigDecimal.ZERO;
        if (!order.getExchange()) {
            orderMoney = MathUtils.multiply(childOrder.getRealPrice(), new BigDecimal(dto.getRefundNum()));

            if (childOrder.getNumber().equals(dto.getRefundNum())) {
                orderMoney = MathUtils.subtractMulti(orderMoney, childOrder.getFirstOrderReduced(),childOrder.getShopCouponSharing(),childOrder.getPlatformCouponSharing(),childOrder.getPlatformPointZxSharing());

            } else {
                double v = childOrder.getFirstOrderReduced().doubleValue() * dto.getRefundNum() / childOrder.getNumber();
                double s = childOrder.getShopCouponSharing().doubleValue() * dto.getRefundNum() / childOrder.getNumber();
                double p = childOrder.getPlatformCouponSharing().doubleValue() * dto.getRefundNum() / childOrder.getNumber();
                double z = childOrder.getPlatformPointZxSharing().doubleValue() * dto.getRefundNum() / childOrder.getNumber();
                orderMoney = MathUtils.subtractMulti(orderMoney, MathUtils.setScale(v),MathUtils.setScale(s),MathUtils.setScale(p),MathUtils.setScale(z));
            }
            //候鸟运费
            if (childOrder.getThird() && StringUtils.equalsIgnoreCase("壹品跨境供应链", childOrder.getSourceShopName())){
                BigDecimal realFreight = order.getRealFreight();
                BigDecimal addRealFreight = orderMoney.add(realFreight);
                //申请的维权金额不能超过订单实际金额
                if (dto.getRefundMoney().compareTo(addRealFreight) > 0) {
                    throw new RRException(String.format(OrderException.OVERFLOW_ORDER_FACT_COST.getMsg(), orderMoney.toString()), OrderException.OVERFLOW_ORDER_FACT_COST.getCode());
                }
            }else {
                //申请的维权金额不能超过订单实际金额
                if (dto.getRefundMoney().compareTo(orderMoney) > 0) {
                    throw new RRException(String.format(OrderException.OVERFLOW_ORDER_FACT_COST.getMsg(), orderMoney.toString()), OrderException.OVERFLOW_ORDER_FACT_COST.getCode());
                }
            }

        } else {
            BigDecimal orderPoint = MathUtils.multiply(new BigDecimal(dto.getRefundNum()),childOrder.getExchangePoint());
            if (dto.getRefundPoint() .compareTo(orderPoint) > 0) {
                throw new RRException(String.format(OrderException.OVERFLOW_ORDER_FACT_POINT.getMsg(), orderPoint), OrderException.OVERFLOW_ORDER_FACT_POINT.getCode());
            }

        }


//        if(order.getThird())
//        {
//            beforeCheck(dto, order, childOrder);
//        }

        // 维权子订单构建
        /**
         * 第一步创建维权订单
         */
        RightsOrder rightsOrder = build(order, dto);
        rightsOrder.setRefundNum(dto.getRefundNum());
        rightsOrder.setIsAllRights(false);
        rightsOrder.setAreaFeature(order.getAreaFeature());
        this.create(rightsOrder);
        /**
         * 第二步创建维权订单明细
         */
        RightsChildOrder rightsChild = build(rightsOrder, childOrder, dto.getRefundNum(), dto.getRefundMoney(), dto.getRefundPoint());
        rightsChildOrderService.create(rightsChild);

        //更新子订单的维权状态
        childOrder.setRightsStatus(OrderConstant.RightsStatus.BEING);
        childOrder.setRightsType(rightsOrder.getRightsType());
        childOrderService.modify(childOrder);

        /**
         * 第三步创建维权订单操作日志
         */
        createRecord(rightsOrder.getId(), rightsOrder.getRightsOperateStatus(), rightsOrder.getReason(), rightsOrder.getVoucherImages(), RightsOrderConstant.RightsOperatePerson.USER);

        /**
         * 第三步，如果此订单是维权订单，则需要将维权数据推送到点三方系统中
         */
        if(order.getThird()) {
            JSONObject req = new JSONObject();
            req.put("post_type", String.valueOf(dto.getThirdPostType()));
            req.put("order_no", String.valueOf(childOrder.getThirdOrderNo()));
            req.put("order_id", "0");
            req.put("source_sale_sn", String.valueOf(rightsOrder.getRightsCode()));
            req.put("num", String.valueOf(childOrder.getNumber()));
            req.put("gather_money", String.valueOf(childOrder.getTotalRealPrice()));

            String refund_description = String.valueOf(dto.getReason());
            if(StringUtils.isNotBlank(refund_description)) {
                req.put("refund_description", refund_description);
            }

            String addenda_img = joinImgUrl(dto.getThirdAddendaImg());
            if(StringUtils.isNotBlank(addenda_img)) {
                req.put("addenda_img", addenda_img);
            }

            String express_img = joinImgUrl(dto.getThirdExpressImg());
            if(StringUtils.isNotBlank(express_img)) {
                req.put("express_img", express_img);
            }

            String package_img = joinImgUrl(dto.getThirdPackageImg());
            if(StringUtils.isNotBlank(package_img)) {
                req.put("package_img", package_img);
            }

            String product_img = joinImgUrl(dto.getThirdProductImg());
            if(StringUtils.isNotBlank(product_img)) {
                req.put("product_img", product_img);
            }

            String defect_product_img = joinImgUrl(dto.getThirdDefectProductImg());
            if(StringUtils.isNotBlank(defect_product_img)) {
                req.put("defect_product_img", defect_product_img);
            }

            String product_shelf_life_img = joinImgUrl(dto.getThirdProductShelfLifeImg());
            if(StringUtils.isNotBlank(product_shelf_life_img)) {
                req.put("product_shelf_life_img", product_shelf_life_img);
            }

            String refund_reason_id = String.valueOf(dto.getThirdRefundReasonId());
            if(StringUtils.isNotBlank(refund_reason_id)) {
                req.put("refund_reason_id", refund_reason_id);
            }

            try {
                JSONObject js = houniaoApiUtil.client(req, HouniaoConstant.AFTER_SALE_APPLY.getUrl());
                if(200 != js.getIntValue("code")){
                    throw new RRException(js.getString("msg"), js.getIntValue("code"));
                }
            } catch (Exception ex) {
                throw new RuntimeException(ex.getLocalizedMessage());
            }
        }


//        if(rightsOrder.getThird())
//        {
//            AfterSaleParam param = AfterSaleParam.builder()
//                    .orderSn(order.getOrderCode())
//                    .sku(rightsChild.getThirdSkuId())
//                    .num(rightsChild.getRefundNum())
//                    .logisticFee(0D)
//                    .serviceTypeCode(dto.getThirdServiceType())
//                    .reasonsDescription(dto.getReason())
//                    .vouchers(dto.getVoucherImages().toArray(new String[0]))
//                    .build();
//            if(StringUtils.isNotEmpty(dto.getThirdReasonsTypeCode()))
//            {
//                param.setReasonsTypeCode(dto.getThirdReasonsTypeCode());
//            }
//            if(StringUtils.isNotEmpty(dto.getThirdPackageTypeCode()))
//            {
//                param.setPackageTypeCode(dto.getThirdPackageTypeCode());
//            }
//            if(OrderConstant.RightsType.RETURN.equals(rightsOrder.getRightsType()))
//            {
//                param.setPickTypeCode("50");
//            }
//            AfterSale afterSale = apiAfterSaleCommon.afterSale(param);
//            rightsOrder.setThirdRightsId(afterSale.getId());
//            this.modify(rightsOrder);
//        }
        return rightsOrder;
    }

    private String joinImgUrl(String[] imgUrls){
        if(imgUrls == null || imgUrls.length == 0){ return null;}
        return Arrays.stream(imgUrls).filter(StringUtils::isNotBlank).collect(Collectors.joining(","));
    }

    private void beforeCheck(ApplyOrderRightsDTO dto, Order order, ChildOrder childOrder) {
        BeforeCheckParam build = BeforeCheckParam.builder()
                .orderSn(order.getOrderCode()).sku(childOrder.getThirdSkuId()).build();
        BeforeCheck beforeCheck = apiAfterSaleCommon.beforeCheck(build);
        if(dto.getRightsType()==1 && "50".equals(dto.getThirdServiceType()))
        {
            throw new RRException("申请的仅退款标识不统一");
        }
        if(dto.getRightsType()==2 && "40".equals(dto.getThirdServiceType()))
        {
            throw new RRException("申请的退货退款标识不统一");
        }


        BeforeCheck.ServiceType[] serviceType = beforeCheck.getServiceType();
        if(serviceType.length==0)
        {
            throw new RRException("该商品已不能参与售后");
        }
        Boolean isFind = false;
        for (int i=0;i<serviceType.length;i++)
        {
            if(serviceType[i].getCode().equals(dto.getThirdServiceType()))
            {
                isFind = true;
                break;
            }
        }
        if(!isFind)
        {
            throw new RRException("该商品已不能参与"+ OrderConstant.RightsType.getByCode(dto.getRightsType()));
        }

        if(dto.getRightsType()==1 && !dto.getRefundNum().equals(childOrder.getNumber()))
        {
            throw new RRException("申请仅退款只能商品全退");
        }
    }


    /**
     * 商家同意维权
     *
     * @param shopId
     * @param dto
     * @return
     */
    @DistributedLock(lockNamePre = LockPrefixConstant.AGREE_OR_REFUSE_RIGHTS, argNum = 2,param = "rightsOrderId")
    @Transactional(rollbackFor = Exception.class)
    @Override
    public RightsOrder agree(Long shopId, RightsOrderOperateDTO dto) {
        RightsOrder rightsOrder = this.loadByShopIdAndId(shopId, dto.getRightsOrderId(), true);
        //1、什么情况下商家可以同意
        //只有刚刚申请的维权单,商家才可以同意或拒绝
        if (!RightsOrderConstant.RightsOperateStatus.APPLY.equals(rightsOrder.getRightsOperateStatus())) {
            throw new RRException(OrderException.RIGHTS_ORDER_NOT_APPLY);
        }
        /**
         * 第一步修改维权单的状态成为已同意
         */
        rightsOrder = agree(rightsOrder);

        /**
         * 第二步创建维权订单操作日志
         */
         createRecord(rightsOrder.getId(), rightsOrder.getRightsOperateStatus(), dto.getReason(), new ArrayList<>(), RightsOrderConstant.RightsOperatePerson.SHOP);

         return rightsOrder;
    }

    /**
     * 系统自动同意维权
     *
     * @param rightsOrder
     */
    @Transactional
    @Override
    public RightsOrder autoAgree(RightsOrder rightsOrder) {
        if (!rightsOrder.getValid()) {
            throw new RRException(OrderException.RIGHTS_ORDER_DISABLED);
        }

        if (!RightsOrderConstant.RightsOperateStatus.APPLY.equals(rightsOrder.getRightsOperateStatus())) {
            throw new RRException(OrderException.NOT_APPLY_NOT_AGREE);
        }
        /**
         * 第一步修改维权单的状态成为已同意
         */
        rightsOrder = agree(rightsOrder);

        /**
         * 第二步创建维权订单操作日志
         */
        createRecord(rightsOrder.getId(), rightsOrder.getRightsOperateStatus(), "系统自动同意", new ArrayList<>(), RightsOrderConstant.RightsOperatePerson.SYSTEM);
        return rightsOrder;
    }

    //修改维权单的状态成为已同意
    private RightsOrder agree(RightsOrder rightsOrder) {
        if (rightsOrder.getShopName().equals("壹品跨境供应链")){
            //<editor-fold desc="售后申请">
            JSONObject afterSale = new JSONObject();
            ChildOrder childOrder = childOrderService.getOne(new LambdaQueryWrapper<ChildOrder>().eq(ChildOrder::getOrderCode, rightsOrder.getOrderCode()));
//            afterSale.put("order_id",childOrder.getThirdOrderNo());
            afterSale.put("order_no", childOrder.getThirdOrderNo());
            afterSale.put("source_sale_sn",rightsOrder.getOrderCode());
            afterSale.put("post_type",1);
            afterSale.put("refund_reason_id",1);
            afterSale.put("num",rightsOrder.getRefundNum());
//            afterSale.put("refund_description",rightsOrder.getCaption());
            afterSale.put("refund_description","退款");
            JSONObject afterSaleJState = null;
            /*
            String msg = "";
            try {
                JSONObject afterSaleJs = houniaoApiUtil.client(afterSale, HouniaoConstant.AFTER_SALE_APPLY.getUrl());
                afterSaleJState = afterSaleJs;
                msg = String.valueOf(afterSaleJState.get("msg"));
            }catch (Exception e){
                JSONObject afterSaleDetail = new JSONObject();
                afterSaleDetail.put("order_no",childOrder.getThirdOrderNo());
                String saleStatus = "";
                JSONObject afterSaleJs = null;
                try {
                    afterSaleJs = houniaoApiUtil.client(afterSaleDetail, HouniaoConstant.AFTER_SALE_DETAIL.getUrl());
                }catch (Exception ee){
                    throw new RRException("候鸟售后详情获取异常：" + ee.getLocalizedMessage());
                }
//                if (saleStatus.equals("0")){
//                    throw new RRException("第三方平台处理中...");
//                }
                JSONObject data = afterSaleJs.getJSONObject("data");
                if(data != null) {
                    afterSaleJState = afterSaleJs;
                    // 获取售后的工单状态
                    //工单状态：-1表示已取消，0表示待受理（商家未处理状态），1表示受理中，2表示拒绝，3表示已完结（已退款），
                    // 4表示等待买家退货（消费者未处理），5表示已退货待收货（商家未处理），6表示已收货换货中（商家未处理）
                    saleStatus = String.valueOf(data.get("post_sale_status"));
                    switch (saleStatus) {
                        case "-1":
                            throw new RRException("第三方平台已取消");
                        case "0":
                            throw new RRException("第三方平台待受理");
                        case "1":
                            throw new RRException("第三方平台处理中");
                        case "2":
                            throw new RRException("第三方平台拒绝");
                        case "4":
                            throw new RRException("第三方平台等待买家退货");
                        case "5":
                            throw new RRException("已退货第三方平台待收货");
                        case "6":
                            throw new RRException("第三方平台已收货换货中");
                        case "3":
                        default:
                            break;
                    }
                } else {
                    throw new RRException("候鸟售后详情获取失败：商品详情数据是空的");
                }
            }
            //</editor-fold>

            //<editor-fold desc="售后详情"
            if (StringUtils.equals(String.valueOf(afterSaleJState.get("code")),"200")){
             */

                JSONObject afterSaleDetail = new JSONObject();
//                afterSaleDetail.put("id",childOrder.getThirdOrderNo());
                afterSaleDetail.put("order_no",childOrder.getThirdOrderNo());
                JSONObject afterSaleJs = null;
                try {
                    afterSaleJs = houniaoApiUtil.client(afterSaleDetail, HouniaoConstant.AFTER_SALE_DETAIL.getUrl());
                }catch (Exception e){
                    throw new RuntimeException("候鸟售后详情获取异常：" + e.getLocalizedMessage());
                }

                JSONObject data = null;
                if(afterSaleJs == null || (data = afterSaleJs.getJSONObject("data")) == null){
                    throw new RRException("候鸟售后详情获取失败：商品详情数据是空的");
                } else {
                    String saleStatus = "";
                    afterSaleJState = afterSaleJs;
                    // 获取售后的工单状态
                    //工单状态：-1表示已取消，0表示待受理（商家未处理状态），1表示受理中，2表示拒绝，3表示已完结（已退款），
                    // 4表示等待买家退货（消费者未处理），5表示已退货待收货（商家未处理），6表示已收货换货中（商家未处理）
                    saleStatus = String.valueOf(data.get("post_sale_status"));
                    switch (saleStatus) {
                        case "-1":
                            throw new RRException("第三方平台已取消");
                        case "0":
                            throw new RRException("第三方平台待受理");
                        case "1":
                            throw new RRException("第三方平台处理中");
                        case "2":
                            throw new RRException("第三方平台拒绝");
                        case "4":
                            throw new RRException("第三方平台等待买家退货");
                        case "5":
                            throw new RRException("已退货第三方平台待收货");
                        case "6":
                            throw new RRException("第三方平台已收货换货中");
                        case "3":
                        default:
                            break;
                    }
                }
            /*
            }else {
                throw new RRException("候鸟售后申请失败：" + afterSaleJState.get("msg"));
            }
             */
            //</editor-fold>
        }

        rightsOrder.setRightsOperateStatus(RightsOrderConstant.RightsOperateStatus.AGREE);
        if (OrderConstant.RightsType.RETURN.equals(rightsOrder.getRightsType())) {
            /**
             * 计算最后发货时间
             */
            SaleConfig config = saleConfigService.getConfig();
            Integer day = SaleConfig.defaultRightsDays;
            if (config != null) {
                /**
                 *  商家同意退货多少天后买家未处理，系统将自动拒绝维权
                 */
                day = config.getAgreeReturnAutoProcessDays();
            }
            long lastShipTime = OrderConstant.getTomorrowAndDayTimestamp(System.currentTimeMillis(), day);
            rightsOrder.setLastShipTime(lastShipTime);
        }
        this.modify(rightsOrder);
        return rightsOrder;
    }

    /**
     * 商家拒绝维权
     *
     * @param shopId
     * @param dto
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @DistributedLock(lockNamePre = LockPrefixConstant.AGREE_OR_REFUSE_RIGHTS, argNum = 2,param = "rightsOrderId")
    @Override
    public RightsOrder refuse(Long shopId, RightsOrderOperateDTO dto) {
        RightsOrder rightsOrder = this.loadByShopIdAndId(shopId, dto.getRightsOrderId(), true);
        //1、什么情况下商家可以拒绝
        //只有刚刚申请的维权单,商家才可以同意或拒绝
        if (!RightsOrderConstant.RightsOperateStatus.APPLY.equals(rightsOrder.getRightsOperateStatus())) {
            throw new RRException(OrderException.RIGHTS_ORDER_NOT_APPLY);
        }
        /**
         * 第一步修改维权单的状态成为已拒绝，并且当前维权已无效
         */
        rightsOrder.setRightsOperateStatus(RightsOrderConstant.RightsOperateStatus.REFUSE);
        rightsOrder.setValid(false);
        this.modify(rightsOrder);
        /**
         * 第二步创建维权订单操作日志
         */
        createRecord(rightsOrder.getId(), rightsOrder.getRightsOperateStatus(), dto.getReason(), new ArrayList<>(), RightsOrderConstant.RightsOperatePerson.SHOP);

        /**
         * 第三步取消维权
         */
        cancel(rightsOrder);

        return rightsOrder;
    }

    /**
     * 手动取消维权
     *
     * @param userId
     * @param rightsId
     * @return
     */
    @Override
    @Transactional
    public RightsOrder cancel(Long userId, Long rightsId) {
        RightsOrder rightsOrder = this.loadByUserAndId(userId, rightsId, true);
        /* 新的业务要求无论什么情况下都可以取消维权 at 2024-06-05
        if(rightsOrder.getThird()) {
            throw new RRException("第三方的维权订单不能取消");
        }
        //1、什么情况下会员可以手动取消维权
        // 如果是退款
        if (rightsOrder.getRightsType().equals(OrderConstant.RightsType.REFUND)) {
            //只有刚刚申请的退款维权单,会员才可以取消
            if (!RightsOrderConstant.RightsOperateStatus.APPLY.equals(rightsOrder.getRightsOperateStatus())) {
                throw new RRException(OrderException.REFUND_RIGHTS_NOT_CANCEL);
            }
        }
        //如果是退货退款
        if (rightsOrder.getRightsType().equals(OrderConstant.RightsType.RETURN)) {
            //退款退货维权单,会员发货之后不能取消
            if (!(RightsOrderConstant.RightsOperateStatus.APPLY.equals(rightsOrder.getRightsOperateStatus())
                    || RightsOrderConstant.RightsOperateStatus.AGREE.equals(rightsOrder.getRightsOperateStatus()))) {
                throw new RRException(OrderException.RETURN_RIGHTS_NOT_CANCEL);
            }
        }
         */

        /**
         * 第一步修改维权单的状态成为已拒绝，并且当前维权已无效
         */
        rightsOrder.setRightsOperateStatus(RightsOrderConstant.RightsOperateStatus.CANCEL);
        rightsOrder.setValid(false);
        this.modify(rightsOrder);
        /**
         * 第二步创建维权订单操作日志
         */
        createRecord(rightsOrder.getId(), rightsOrder.getRightsOperateStatus(), "", new ArrayList<>(), RightsOrderConstant.RightsOperatePerson.USER);
        /**
         * 第三步自动取消维权
         */
        cancel(rightsOrder);

        return rightsOrder;
    }

    /**
     * 过期没有填写物流退货信息
     *
     * @param rightsOrder
     */
    @Transactional
    @Override
    public void autoCancel(RightsOrder rightsOrder) {

        if (!rightsOrder.getRightsType().equals(OrderConstant.RightsType.RETURN)) {
            throw new RRException(OrderException.NOT_RIGHTS_RETURN);
        }
        //如果是退货退款
        //退款退货维权单,会员发货之后不能取消
        if (!RightsOrderConstant.RightsOperateStatus.AGREE.equals(rightsOrder.getRightsOperateStatus())) {

            throw new RRException(OrderException.RETURN_SHIP_AFTER_NOT_CANCEL);
        }

        /**
         * 第一步修改维权单的状态成为已取消
         */
        rightsOrder.setRightsOperateStatus(RightsOrderConstant.RightsOperateStatus.AUTO_CLOSE);
        rightsOrder.setValid(false);
        this.modify(rightsOrder);
        /**
         * 第二步创建维权订单操作日志
         */
        createRecord(rightsOrder.getId(), rightsOrder.getRightsOperateStatus(), "", new ArrayList<>(), RightsOrderConstant.RightsOperatePerson.SYSTEM);
        /**
         * 第三步自动取消维权
         */
        cancel(rightsOrder);
    }


    /**
     * 退货退款单商家同意之后，会员填写发货单
     *
     * @param userId
     * @param dto
     * @return
     */
    @Transactional
    @Override
    public RightsOrder ship(Long userId, RightsOrderShipDTO dto) {
        RightsOrder rightsOrder = this.loadByUserAndId(userId, dto.getRightsOrderId(), true);
        RightsOrderShipRecord rightsOrderShipRecord = shipRecordService.loadByRightsId(rightsOrder.getId(), false);
        if (!rightsOrder.getRightsType().equals(OrderConstant.RightsType.RETURN)) {
            //退款退货维权单才可以发货
            throw new RRException(OrderException.NOT_RIGHTS_RETURN);
        }

        if (rightsOrderShipRecord == null) {
            /**
             * 什么情况下可以会员可以填发货单
             */
            if (!RightsOrderConstant.RightsOperateStatus.AGREE.equals(rightsOrder.getRightsOperateStatus())) {
                //退款退货维权单同意后发货
                throw new RRException(OrderException.RIGHTS_AGREE_AFTER_SHIP);
            }

            /**
             * 第一步会员填写发货单
             */
            RightsOrderShipRecord shipRecord = new RightsOrderShipRecord();
            BeanUtil.copyPropertiesIgnoreNull(dto, shipRecord);
            shipRecord.setRightsOrderId(rightsOrder.getId());
            shipRecordService.create(shipRecord);

            /**
             * 第二步修改维权单的状态成为已发货
             */
            rightsOrder.setRightsOperateStatus(RightsOrderConstant.RightsOperateStatus.USER_SHIP);
            /**
             * 计算最后发货时间
             */
            SaleConfig config = saleConfigService.getConfig();
            Integer day = SaleConfig.defaultRightsDays;
            if (config != null) {
                /**
                 *  买家已退货(退货填单)多少天后商家未处理，系统将自动收货。
                 */
                day = config.getReturnedAutoProcessDays();
            }
            long lastReceiptTime = OrderConstant.getTomorrowAndDayTimestamp(System.currentTimeMillis(), day);
            rightsOrder.setLastReceiptTime(lastReceiptTime);
            this.modify(rightsOrder);

            /**
             * 第三步创建维权订单操作日志
             */
            createRecord(rightsOrder.getId(), rightsOrder.getRightsOperateStatus(), "", new ArrayList<>(), RightsOrderConstant.RightsOperatePerson.USER);

            if(rightsOrder.getThird()) {
                AfterSaleMailParam build = AfterSaleMailParam.builder()
                        .id(rightsOrder.getThirdRightsId())
                        .company(shipRecord.getExpressCode())
                        .sn(shipRecord.getLogisticCode())
                        .vouchers(dto.getThirdVouchers().toArray(new String[0]))
                        .build();
                apiAfterSaleCommon.afterSaleMail(build);
            }

        } else {
            if (!RightsOrderConstant.RightsOperateStatus.USER_SHIP.equals(rightsOrder.getRightsOperateStatus())) {
                //退款退货维权单同意后发货
                throw new RRException(OrderException.RIGHTS_RETURN_ABLE_UPDATE_SHIP);
            }
            if (!dto.getLogisticCode().equals(rightsOrderShipRecord.getLogisticCode())) {
                BeanUtil.copyPropertiesIgnoreNull(dto, rightsOrderShipRecord);
                shipRecordService.modify(rightsOrderShipRecord);
            }
        }

        return rightsOrder;
    }

    /**
     * 退货退款单会员填写发货单发货之后，商家收货
     *
     * @param shopId
     * @param dto
     * @return
     */
    @Transactional
    @Override
    public RightsOrder receipt(Long shopId, RightsOrderOperateDTO dto) {
        RightsOrder rightsOrder = this.loadByShopIdAndId(shopId, dto.getRightsOrderId(), true);
        if (!rightsOrder.getRightsType().equals(OrderConstant.RightsType.RETURN)) {
            //不是退款退货维权单
            throw new RRException(OrderException.NOT_RIGHTS_RETURN);
        }
        if (!RightsOrderConstant.RightsOperateStatus.USER_SHIP.equals(rightsOrder.getRightsOperateStatus())) {
            //退款退货维权单还没有发货
            throw new RRException(OrderException.RIGHTS_NOT_SHIP);
        }

        /**
         * 第一步修改维权单的状态成为已收货
         */
        rightsOrder.setRightsOperateStatus(RightsOrderConstant.RightsOperateStatus.SHOP_RECEIPT);
        this.modify(rightsOrder);

        /**
         * 第二步创建维权订单操作日志
         */
        createRecord(rightsOrder.getId(), rightsOrder.getRightsOperateStatus(), "", new ArrayList<>(), RightsOrderConstant.RightsOperatePerson.SHOP);

        return rightsOrder;
    }

    /**
     * 自动收货
     *
     * @param rightsOrder
     */
    @Transactional
    @Override
    public void autoReceipt(RightsOrder rightsOrder) {
        if (!RightsOrderConstant.RightsOperateStatus.USER_SHIP.equals(rightsOrder.getRightsOperateStatus())) {
            throw new RRException("只有会员发货的维权单才可以自动收货");
        }
        /**
         * 第一步修改维权单的状态成为已收货
         */
        rightsOrder.setRightsOperateStatus(RightsOrderConstant.RightsOperateStatus.SHOP_RECEIPT);
        this.modify(rightsOrder);

        /**
         * 第二步创建维权订单操作日志
         */
        createRecord(rightsOrder.getId(), rightsOrder.getRightsOperateStatus(), "", new ArrayList<>(), RightsOrderConstant.RightsOperatePerson.SYSTEM);
    }

    /**
     * 商家退款
     *
     * @param shopId
     * @param dto
     * @return
     */
    @Transactional
    @Override
    public PayRefundOrder refund(Long shopId, RightsOrderOperateDTO dto) {
        // 查找维权单
        RightsOrder rightsOrder = this.loadByShopIdAndId(shopId, dto.getRightsOrderId(), true);
        // 判断维权单状态是否为 退款
        if (OrderConstant.RightsType.REFUND.equals(rightsOrder.getRightsType())) {
            //退款单同意之后才可以退款
            if (!RightsOrderConstant.RightsOperateStatus.AGREE.equals(rightsOrder.getRightsOperateStatus()) &&
                    !RightsOrderConstant.RightsOperateStatus.SEND_REFUND.equals(rightsOrder.getRightsOperateStatus())) {
                // 抛异常 退款单同意之后才可以退款
                throw new RRException(OrderException.AGREE_REFUND);
            }
        }
        // 判断维权单状态是否为 退货退款
        if (OrderConstant.RightsType.RETURN.equals(rightsOrder.getRightsType())) {
            //退款退货单收货之后才可以退款
            if (!RightsOrderConstant.RightsOperateStatus.SHOP_RECEIPT.equals(rightsOrder.getRightsOperateStatus()) &&
                    !RightsOrderConstant.RightsOperateStatus.SEND_REFUND.equals(rightsOrder.getRightsOperateStatus())) {
                // 抛异常 退款退货单收货之后才可以退款
                throw new RRException(OrderException.SHOP_RECEIPT_REFUND);
            }
        }
        // 判断维权单状态是否为 "退款成功" 维权退款状态（0待退款，1退款成功，2退款失败）
        if (RightsOrderConstant.RightsRefundStatus.SUCCESS.equals(rightsOrder.getRightsRefundStatus())) {
            // 抛出退款已成功不要重复
            throw new RRException(OrderException.REPEAT_REFUND);
        }
        // 退款支付
        return refund(rightsOrder);
    }


    @Override
    @DistributedLock(lockNamePre = LockPrefixConstant.THIRD_REFUND, argNum = 1)
    @Transactional(rollbackFor = Exception.class)
    public PayRefundOrder thirdRefund(Long afterSaleId)
    {
        RightsOrder rightsOrder = this.loadByThirdRightsId(afterSaleId);
        if(ObjectUtil.isNull(rightsOrder))
        {
            throw new RRException("不存在退款对象");
        }

        if(RightsOrderConstant.RightsRefundStatus.SUCCESS.equals(rightsOrder.getRightsRefundStatus()))
        {
            throw new RRException("已退款不能重退");
        }

        PayRefundOrder payRefundOrder = createPayRefundOrder(rightsOrder);


        if (rightsOrder.getPayRefundId() == 0) {
            /**
             * 第二步修改维权单状态，记录退款支付订单
             */
            rightsOrder.setPayRefundCode(payRefundOrder.getRefundCode());
            rightsOrder.setPayRefundId(payRefundOrder.getId());
            rightsOrder.setRightsOperateStatus(RightsOrderConstant.RightsOperateStatus.REFUND_COMPLETE);
            this.modify(rightsOrder);
            /**
             * 第三步创建维权订单操作日志
             */
            createRecord(rightsOrder.getId(), rightsOrder.getRightsOperateStatus(), "", new ArrayList<>(), RightsOrderConstant.RightsOperatePerson.SYSTEM);
        }
        /**
         * 第四步发起退款
         */
        return refundMoney(rightsOrder, payRefundOrder);

    }

    private PayRefundOrder refundMoney(RightsOrder rightsOrder, PayRefundOrder payRefundOrder) {
        if (OrderConstant.PayMode.BALANCE.equals(rightsOrder.getPayMode())
                || OrderConstant.PayMode.POINT_BALANCE.equals(rightsOrder.getPayMode())
                || OrderConstant.PayMode.POINT.equals(rightsOrder.getPayMode())) {

            return toBalancePayRefundOrder(rightsOrder, payRefundOrder);
        }
        return toPayRefundOrder(rightsOrder, payRefundOrder);
    }

    /**
     * @param rightsOrder
     * @return
     */
    private PayRefundOrder refund(RightsOrder rightsOrder) {

        /**
         * 第一步创建退款支付订单
         */
        PayRefundOrder payRefundOrder = createPayRefundOrder(rightsOrder);


        if (rightsOrder.getPayRefundId() == 0) {
            /**
             * 第二步修改维权单状态，记录退款支付订单
             */
            rightsOrder.setPayRefundCode(payRefundOrder.getRefundCode());
            rightsOrder.setPayRefundId(payRefundOrder.getId());
            rightsOrder.setRightsOperateStatus(RightsOrderConstant.RightsOperateStatus.SEND_REFUND);
            this.modify(rightsOrder);
            /**
             * 第三步创建维权订单操作日志
             */
            createRecord(rightsOrder.getId(), rightsOrder.getRightsOperateStatus(), "", new ArrayList<>(), RightsOrderConstant.RightsOperatePerson.SHOP);

        }

        /**
         * 第四步发起退款
         */
        return refundMoney(rightsOrder, payRefundOrder);
    }

    @NotNull
    private PayRefundOrder toBalancePayRefundOrder(RightsOrder rightsOrder, PayRefundOrder payRefundOrder) {
        if (payRefundOrder.getRefundPoint().compareTo(BigDecimal.ZERO) > 0) {
            integralRecordService.inner(new IntegralRecord(payRefundOrder.getUserId(), payRefundOrder.getRefundPoint(),
                    IntegralConstant.InnerMode.POINT_ORDER_REFUND, IntegralConstant.IntegralModelType.RIGHTS_ORDER, rightsOrder.getId(),
                    String.format("维权订单[%s]退回积分:%s", rightsOrder.getOrderCode(), rightsOrder.getRefundPoint())));
        }

        if (payRefundOrder.getRefundMoney().compareTo(BigDecimal.ZERO) > 0) {
            saleRefillCardBillService.addBalance(rightsOrder.getUserId(), rightsOrder.getRefundMoney(), rightsOrder.getRightsCode(), BillConstant.InnerMode.SALE_ROLLBACK);
        }

        payRefundOrderService.setRefundStatus(payRefundOrder, RightsOrderConstant.RightsRefundStatus.SUCCESS);
        refundSuccessOperate(rightsOrder);
        return payRefundOrder;
    }

    @Nullable
    private PayRefundOrder toPayRefundOrder(RightsOrder rightsOrder, PayRefundOrder payRefundOrder) {
        String result = "";
        String errorMsg = "";
        try {
            Order order = rightsOrder.loadOrder();
            PayOrder payOrder = order.loadPayOrder();
            SaleOrderReductionRecord saleOrderReductionRecord = null;
            if (GoodsConstant.AreaFeature.ACTIVATING.equals(order.getAreaFeature())){
                saleOrderReductionRecord = saleOrderReductionRecordService.getOne(new LambdaQueryWrapper<SaleOrderReductionRecord>().eq(SaleOrderReductionRecord::getPayCode, payOrder.getCode()));
            }
            String description = OrderConstant.OrderType.REFILL_ORDER.equals(payOrder.getOrderType()) ? "转入" : "";
            String clientIp = "127.0.0.1";
            Integer payType = 0;
            OrderConstant.PayMode byCode = order.getPayMode();
            if (OrderConstant.PayMode.WE_CHAT.equals(byCode)) {
                payType = PayConstant.PayType.WECHAT_TRADE_APPLET_PAY.getCode();
            } else if (OrderConstant.PayMode.ALIPAY.equals(byCode)) {
                payType = PayConstant.PayType.ALIPAY_TRADE_APP_PAY.getCode();
            } else if (OrderConstant.PayMode.ALIPAY_HUIFU.equals(byCode)) {
                payType = PayConstant.PayType.ORDER_PAY_TYPE_ALIPAY_HUIFU_APP.getCode();
            } else if (OrderConstant.PayMode.KJ.equals(byCode)) {
                payType = PayConstant.PayType.ORDER_PAY_TYPE_ADAPAY_KJ_APP.getCode();
            } else if (OrderConstant.PayMode.ALIPAY_HSQ.equals(byCode)) {
                payType = PayConstant.PayType.ORDER_PAY_TYPE_ALIPAY_HSQ_MAIN.getCode();
            } else if (OrderConstant.PayMode.QUICK_PAY_ALIPAY.equals(byCode)) {
                payType = PayConstant.PayType.QUICK_PAY_ALIPAY.getCode();
            } else if (OrderConstant.PayMode.QUICK_PAY_AWE_CHAT.equals(byCode)) {
                payType = PayConstant.PayType.QUICK_PAY_AWE_CHAT.getCode();
            } else if (OrderConstant.PayMode.QUICK_PAY.equals(byCode)) {
                payType = PayConstant.PayType.QUICK_PAY.getCode();
            }else if (OrderConstant.PayMode.QUICK_PAY_BANK.equals(byCode)) {
                payType = PayConstant.PayType.QUICK_PAY_BANK.getCode();
            } else {
                payType = PayConstant.PayType.BALANCE.getCode();
            }
            Map<String, Object> m = new HashMap<String, Object>();

            // 快钱支付
            if (PayConstant.PayType.QUICK_PAY_AWE_CHAT.getCode().equals(payType)
            || PayConstant.PayType.QUICK_PAY_ALIPAY.getCode().equals(payType)
            || PayConstant.PayType.QUICK_PAY.getCode().equals(payType)){
                BigDecimal refundMoney = rightsOrder.getRefundMoney();
                if (saleOrderReductionRecord != null) {
                    refundMoney = saleOrderReductionRecord.getTotalAmountReduction();
                }
                m = InitReFund.gateWayInitReFund(refundMoney,payOrder.getCode(),
                        payOrder.getThirdPayCode(), clientIp, description);
                if(ObjectUtil.equals("1", m.get("resultCode"))){
                    log.info(String.format("快钱退款处理结果：%1$s",m.get("responseMessage")));
                    String refundId = String.valueOf(m.get("idBizCtrl"));
                    BigDecimal money = rightsOrder.getRefundMoney();
                    payRefundOrderService.callbackHandle(payRefundOrder, refundId, money, OrderConstant.PayMode.QUICK_PAY);
                    result = "success";
                } else {
                    errorMsg = String.format("快钱退款异常：%1$s", m.get("errorMessage"));
                }
            }
            // 非快钱支付
            else {
                // 微信
                try {
                    if (OrderConstant.PayMode.WE_CHAT.equals(rightsOrder.getPayMode())
                            || OrderConstant.PayMode.POINT_WE_CHAT.equals(rightsOrder.getPayMode())) {
                        Order thisOrder = rightsOrder.loadOrder();
                        PayOrder thisPayOrder = thisOrder.loadPayOrder();
                        RefundModel refundModel = new RefundModel();
                        refundModel.setPayType(2);
                        refundModel.setPayObject(
                                // 支付渠道 微信小程序 （三元）
                                OrderConstant.ChannelType.WE_APPLET.equals(rightsOrder.loadOrder().loadPayOrder().getChannelType()) ? 1 : 0
                        );

                        // 微信支付订单号 transaction_id 第三方支付单号
                        refundModel.setTradeNo(thisPayOrder.getThirdPayCode());

                        // 支付时用的业务编号
                        refundModel.setOrderNo(thisPayOrder.getCode());

                        // 业务退款单号
                        refundModel.setRefundNo(payRefundOrder.getRefundCode());

                        // 退款总金额, 保留两位小数，四舍五入
                        refundModel.setRefundAmount(rightsOrder.getRefundMoney().setScale(2, BigDecimal.ROUND_HALF_UP));
                        /*
                        // 为了和付款时的算法一致，这里采用了付款时的算法，而不采用上面的算法
                        int refundAmountForWxPay = CalculateUtil.multiply(rightsOrder.getRefundMoney().doubleValue(), 100.0, 2).intValue();
                        refundModel.setRefundAmount(new BigDecimal(refundAmountForWxPay));
                        */

                        // 总费用(包含运费), 保留两位小数，四舍五入
                        refundModel.setTotalFee(thisOrder.getTotalAmount().setScale(2, BigDecimal.ROUND_HALF_UP));
                        /*
                        // 为了和付款时的算法一致，这里采用了付款时的算法，而不采用上面的算法
                        int totalFeeForWxPay = CalculateUtil.multiply(thisOrder.getTotalAmount().doubleValue(), 100.0, 2).intValue();
                        refundModel.setTotalFee(new BigDecimal(totalFeeForWxPay));
                        */

                        // 维权原因
                        refundModel.setRefundReason(rightsOrder.getReason());

                        result = payService.orderRefund(refundModel, (resultMap) -> {
                            Map par = JSONObject.parseObject(JSONObject.toJSONString(resultMap), Map.class);
                            String refundId = par.get("refund_id").toString();//第三方单号(退款)
                            String refundFee = par.get("refund_fee").toString();//订单总金额，单位为分
                            BigDecimal money = MathUtils.divide(new BigDecimal(refundFee), new BigDecimal("100"));
                            payRefundOrderService.callbackHandle(payRefundOrder, refundId, money, OrderConstant.PayMode.WE_CHAT);
                            return "ok";
                        });
                    }
                }
                catch (Exception ex)
                {
                    log.error("微信 退款异常" + ex.getStackTrace() + "RightsOrderServiceImpl.java" + ex.getMessage());
                    System.out.println(ex.getStackTrace());
                    System.out.println("XXXXXX-------Exception："+ex.getMessage());
                    errorMsg = String.format("微信 退款异常：%1$s", ex.getMessage());
                }

                // 支付宝
                try {
                    if (OrderConstant.PayMode.ALIPAY.equals(rightsOrder.getPayMode())
                            || OrderConstant.PayMode.POINT_ALIPAY.equals(rightsOrder.getPayMode())) {
                        Order thisOrder = rightsOrder.loadOrder();
                        PayOrder thisPayOrder = thisOrder.loadPayOrder();
                        RefundModel refundModel = new RefundModel();
                        refundModel.setPayType(1);
                        refundModel.setTradeNo(thisPayOrder.getThirdPayCode());
                        refundModel.setOrderNo(thisPayOrder.getCode());

                        // 下面的语句是误用的，退款时RefundNo用于分账退款，这里没有分账
                        // refundModel.setRefundNo(payRefundOrder.getRefundCode());

                        // 下面的语句是多余的，支付宝用不上
                        //refundModel.setTotalFee(rightsOrder.loadOrder().getTotalAmount());

                        // 下面的语句是误用的，在付款有减免的情况下，不可退全款，而应该是买家减免后的实付金额
                        // refundModel.setRefundAmount(rightsOrder.getRefundMoney());
                        refundModel.setRefundAmount(payOrder.getBuyerPayAmount());

                        refundModel.setRefundReason(rightsOrder.getReason());
                        result = payService.orderRefund(refundModel, (resultMap) -> {
                            AlipayTradeRefundResponse par = (AlipayTradeRefundResponse) resultMap;
                            String refundId = par.getRefundSettlementId();
                            String refundFee = par.getRefundFee();//订单总金额，单位为分
                            BigDecimal money = new BigDecimal(refundFee);
                            payRefundOrderService.callbackHandle(payRefundOrder, refundId, money, OrderConstant.PayMode.ALIPAY);
                            return "ok";
                        });
                    }
                }
                catch (Exception ex)
                {
                    log.error("支付宝 退款异常" + ex.getStackTrace() + "RightsOrderServiceImpl.java" + ex.getMessage());
                    System.out.println(ex.getStackTrace());
                    System.out.println("XXXXXX-------Exception："+ex.getMessage());
                    errorMsg = String.format("支付宝 退款异常：%1$s", ex.getMessage());
                }

                // 汇付
                try {
                    if (OrderConstant.PayMode.POINT_ALIPAY_HUIFU.equals(rightsOrder.getPayMode())
                            || OrderConstant.PayMode.ALIPAY_HUIFU.equals(rightsOrder.getPayMode())) {
                        RefundModel refundModel = new RefundModel();
                        refundModel.setPayType(3);
                        refundModel.setTradeNo(rightsOrder.loadOrder().loadPayOrder().getThirdPayCode());
                        refundModel.setOrderNo(rightsOrder.loadOrder().loadPayOrder().getCode());
                        refundModel.setRefundNo(payRefundOrder.getRefundCode());
                        refundModel.setRefundAmount(rightsOrder.getRefundMoney());
                        refundModel.setTotalFee(rightsOrder.loadOrder().getTotalAmount());
                        refundModel.setRefundReason(rightsOrder.getReason());
                        result = payService.orderRefund(refundModel, (resultMap) -> {
                            Map par = JSONObject.parseObject(JSONObject.toJSONString(resultMap), Map.class);
                            String status = par.get("status").toString();
                            BigDecimal money = new BigDecimal(par.get("refund_amt").toString());
                            String refundId = par.get("id").toString();
                            if("succeeded".equals(status))
                            {
                                payRefundOrderService.callbackHandle(payRefundOrder, refundId, money, OrderConstant.PayMode.ALIPAY_HUIFU);
                            }
                            else
                            {
                                return "no";
                            }
                            return "ok";
                        });
                    }
                }
                catch (Exception ex)
                {
                    log.error("汇付 退款异常" + ex.getStackTrace() + "RightsOrderServiceImpl.java" + ex.getMessage());
                    System.out.println(ex.getStackTrace());
                    System.out.println("XXXXXX-------Exception："+ex.getMessage());
                    errorMsg = String.format("汇付 退款异常：%1$s", ex.getMessage());
                }

                // 快捷支付
                try {
                    if (OrderConstant.PayMode.POINT_KJ.equals(rightsOrder.getPayMode())
                            || OrderConstant.PayMode.KJ.equals(rightsOrder.getPayMode())) {
                        RefundModel refundModel = new RefundModel();
                        refundModel.setPayType(5);
                        refundModel.setTradeNo(rightsOrder.loadOrder().loadPayOrder().getThirdPayCode());
                        refundModel.setOrderNo(rightsOrder.loadOrder().loadPayOrder().getCode());
                        refundModel.setRefundNo(payRefundOrder.getRefundCode());
                        refundModel.setRefundAmount(rightsOrder.getRefundMoney());
                        refundModel.setTotalFee(rightsOrder.loadOrder().getTotalAmount());
                        refundModel.setRefundReason(rightsOrder.getReason());
                        result = payService.orderRefund(refundModel, (resultMap) -> {
                            Map par = JSONObject.parseObject(JSONObject.toJSONString(resultMap), Map.class);
                            String status = par.get("status").toString();
                            BigDecimal money = new BigDecimal(par.get("refund_amt").toString());
                            String refundId = par.get("id").toString();
                            if("succeeded".equals(status))
                            {
                                payRefundOrderService.callbackHandle(payRefundOrder, refundId, money, OrderConstant.PayMode.KJ);
                            }
                            else
                            {
                                return "no";
                            }
                            return "ok";
                        });
                    }
                }
                catch (Exception ex)
                {
                    log.error("快捷支付 退款异常" + ex.getStackTrace() + "RightsOrderServiceImpl.java" + ex.getMessage());
                    System.out.println(ex.getStackTrace());
                    System.out.println("XXXXXX-------Exception："+ex.getMessage());
                    errorMsg = String.format("快捷支付 退款异常：%1$s", ex.getMessage());
                }


                // 快钱快捷支付
                try {
                    if (OrderConstant.PayMode.QUICK_PAY_BANK.equals(rightsOrder.getPayMode())
                            || OrderConstant.PayMode.QUICK_PAY_BANK.equals(rightsOrder.getPayMode())) {


                        JSONObject head = new JSONObject();
                        head.put("version", "1.0.0");
                        head.put("messageType", "A9007");
                        head.put("memberCode", Bill99ConfigInfo.MEMBER_CODE);
                        head.put("externalRefNumber",payOrder.getCode());

                        JSONObject body = new JSONObject();
                        body.put("merchantId",Bill99ConfigInfo.MERCHANT_ID);
                        body.put("terminalId",Bill99ConfigInfo.TERMINAL_ID);
                        body.put("origRefNumber",payOrder.getThirdPayCode());
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
                        body.put("entryTime",sdf.format(new Date()));
                        BigDecimal refundMoney = payOrder.getTotalAmount();
                        if (saleOrderReductionRecord != null) {
                            refundMoney = saleOrderReductionRecord.getTotalAmountReduction();
                        }
                        BigDecimal yuan2fen = refundMoney.multiply(new BigDecimal(100)).setScale(0, RoundingMode.HALF_UP);
                        body.put("amount",yuan2fen.toString());
                        JSONObject originalString = new JSONObject();
                        originalString.put("head", head);
                        originalString.put("requestBody", body);
                        String resStr = buildHttpsClient.requestKQ(originalString);

                        if (StringUtils.isNotBlank(resStr)) {
                            JSONObject res = JSONObject.parseObject(resStr);
                            JSONObject resBody = res.getJSONObject("responseBody");
                            BigDecimal amount = new BigDecimal(resBody.getString("amount")).divide(new BigDecimal(100)).setScale(2, RoundingMode.HALF_UP);
                            String refundId = resBody.getString("refNumber");
                            // 退款成功
                            if ("0000".equals(resBody.getString("bizResponseCode"))) {
                                payRefundOrderService.callbackHandle(payRefundOrder, refundId, amount, OrderConstant.PayMode.QUICK_PAY_BANK);
                                result = "success";
                            }else {
                                errorMsg = String.format("快钱退款异常,退款金额:%s, 快钱退款订单号:%s", amount, refundId);
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    log.error("快钱快捷支付 退款异常" + ex.getStackTrace() + "RightsOrderServiceImpl.java" + ex.getMessage());
                    System.out.println(ex.getStackTrace());
                    System.out.println("XXXXXX-------Exception："+ex.getMessage());
                    errorMsg = String.format("快钱快捷支付 退款异常：%1$s", ex.getMessage());
                }

                //慧收钱
                try {
                    if (OrderConstant.PayMode.POINT_ALIPAY_HSQ.equals(rightsOrder.getPayMode())
                            || OrderConstant.PayMode.ALIPAY_HSQ.equals(rightsOrder.getPayMode())) {
                        RefundModel refundModel = new RefundModel();
                        refundModel.setPayType(4);
                        refundModel.setTradeNo(rightsOrder.loadOrder().loadPayOrder().getThirdPayCode());
                        refundModel.setOrderNo(rightsOrder.loadOrder().loadPayOrder().getCode());
                        refundModel.setRefundNo(payRefundOrder.getRefundCode());
                        refundModel.setRefundAmount(rightsOrder.getRefundMoney());
                        refundModel.setTotalFee(rightsOrder.loadOrder().getTotalAmount());
                        refundModel.setRefundReason(rightsOrder.getReason());
                        result = payService.orderRefund(refundModel, (resultMap) -> {
                            Map par = JSONObject.parseObject(JSONObject.toJSONString(resultMap), Map.class);
                            BigDecimal orderAmt = new BigDecimal(par.get("orderAmt").toString());
                            BigDecimal money = MathUtils.divide(orderAmt, new BigDecimal("100"));
                            String refundId = par.get("tradeNo").toString();
                            if("SUCCESS".equals(par.get("orderStatus").toString())) {
                                payRefundOrderService.callbackHandle(payRefundOrder, refundId, money, OrderConstant.PayMode.ALIPAY_HSQ);
                            }
                            else
                            {
                                return "no";
                            }
                            return "ok";
                        });
                    }
                }
                catch (Exception ex)
                {
                    log.error("慧收钱 退款异常" + ex.getStackTrace() + "RightsOrderServiceImpl.java" + ex.getMessage());
                    System.out.println("慧收钱退款Exception："+ex.getMessage());
                    errorMsg = String.format("慧收钱 退款异常：%1$s", ex.getMessage());
                }
            }
        } catch (Exception e) {
            errorMsg = String.format("系统退款异常：%1$s" ,e.getMessage());
            log.error(errorMsg, e);
        }

        // 退款失败
        if (!result.equals("success") || StringUtils.isNotEmpty(errorMsg)) {
            // 设置 退款系统订单 退款失败
            payRefundOrderService.setRefundStatus(payRefundOrder, RightsOrderConstant.RightsRefundStatus.FAIL);
            // 设置 销售系统中的维权单 退款失败
            rightsOrder.setRightsRefundStatus(RightsOrderConstant.RightsRefundStatus.FAIL);
            // 修改
            this.modify(rightsOrder);

            StringBuffer sb = new StringBuffer();
            if(StringUtils.isNotEmpty(result)){
                sb.append(sb.length() == 0 ? "" : ",");
                sb.append(result);
            }
            if(StringUtils.isNotEmpty(errorMsg)){
                sb.append(sb.length() == 0 ? "" : ",");
                sb.append(errorMsg);
            }
            sb.insert(0, "退款失败：");
            throw new RRException(sb.toString());
        }





        return payRefundOrder;
    }




    /**
     * 维权单商家手动入库
     *
     * @param shopId
     * @param dto
     * @return
     */
    @Transactional
    @Override
    public RightsOrder inStock(Long shopId, RightsInStockDTO dto) {
        RightsOrder rightsOrder = this.loadByShopIdAndId(shopId, dto.getRightsOrderId(), true);
        if (!rightsOrder.getValid()) {
            /**
             * 维权单无效
             */
            throw new RRException(OrderException.RIGHTS_ORDER_DISABLED);
        }
        RightsChildOrder rightsChildOrder = rightsChildOrderService.loadChildRightsOrder(rightsOrder.getId(), dto.getRightsChildOrderId(), true);
        rightsChildOrder.inStock(dto.getNum());
        rightsChildOrderService.modify(rightsChildOrder);

        /**
         * 维权单商家手动入库
         */
        rightsChildOrderInStock(rightsOrder, rightsChildOrder, dto.getNum());

        return rightsOrder;
    }

    @Override
    public RightsOrder loadByPayRefundOrderId(Long payRefundOrderId, boolean tw) {
        RightsOrder one = this.getOne(new LambdaQueryWrapper<RightsOrder>()
                .eq(RightsOrder::getPayRefundId, payRefundOrderId)
                .last("limit 1"));
        if (one == null && tw) {
            throw new RRException(OrderException.RIGHTS_ORDER_NOT_EXISTS);
        }
        return one;
    }

    /**
     * 维权单商家手动入库
     *
     * @param order
     * @param rightsChildOrder
     * @param num
     */
    private void rightsChildOrderInStock(RightsOrder order, RightsChildOrder rightsChildOrder, Integer num) {
        ChildOrder childOrder = rightsChildOrder.getChildOrder();

        OrderStockTo orderStockTo = new OrderStockTo();
        orderStockTo.setChildReferId(childOrder.getId());
        orderStockTo.setSingleGoodsId(childOrder.getSingleGoodsId());
        orderStockTo.setChangeStock(num);
        orderStockTo.setOrderId(childOrder.getOrderId());
        orderStockTo.setGoodsTitle(childOrder.getGoodsTitle());
        orderStockTo.setOrderCode(childOrder.getOrderCode());
        orderStockTo.setOrderId(childOrder.getOrderId());
        orderStockTo.setSingleGoodsId(childOrder.getSingleGoodsId());
        orderStockTo.setSkuSetName(childOrder.getSkuSetName());
        orderStockTo.setUserMobile(childOrder.getMobile());
        orderStockTo.setRightsId(rightsChildOrder.getRightsId());
        orderStockTo.setRightsChildId(rightsChildOrder.getId());
        orderStockTo.setRightsCode(order.getRightsCode());
        productSingleGoodsService.rightsChildOrderInStock(order.getShopId(), orderStockTo);
    }

    /**
     * 创建退款支付订单
     *
     * @param rightsOrder
     * @return
     */
    private PayRefundOrder createPayRefundOrder(RightsOrder rightsOrder) {

        if (rightsOrder.getPayRefundId() > 0) {
            PayRefundOrder obj = payRefundOrderService.getById(rightsOrder.getPayRefundId());
            if (obj == null) {
                throw new RRException(OrderException.PAY_REFUND_ORDER_NOT_EXISTS);
            }
            if (OrderConstant.PayMode.ALIPAY_HSQ.equals(rightsOrder.getPayMode())
                    || OrderConstant.PayMode.POINT_ALIPAY_HSQ.equals(rightsOrder.getPayMode())
                    || OrderConstant.PayMode.ALIPAY_HUIFU.equals(rightsOrder.getPayMode())
                    || OrderConstant.PayMode.POINT_ALIPAY_HUIFU.equals(rightsOrder.getPayMode())
                    || OrderConstant.PayMode.KJ.equals(rightsOrder.getPayMode())
                    || OrderConstant.PayMode.POINT_KJ.equals(rightsOrder.getPayMode())){
                obj.setRefundCode(OrderGen.generateOrderNo());
                payRefundOrderService.modify(obj);

                rightsOrder.setPayRefundCode(obj.getRefundCode());
                this.modify(rightsOrder);
            }
            return obj;
        }

        PayRefundOrder payRefundOrder = new PayRefundOrder();
        payRefundOrder.setUserId(rightsOrder.getUserId());
        payRefundOrder.setMobile(rightsOrder.getMobile());
        payRefundOrder.setOrderType(rightsOrder.getOrderType());
        payRefundOrder.setPayMode(rightsOrder.getPayMode());
        payRefundOrder.setShopId(rightsOrder.getShopId());
        payRefundOrder.setShopName(rightsOrder.getShopName());
        payRefundOrder.setRefundCode(OrderGen.generateOrderNo());
        payRefundOrder.setThirdRefundCode("");
        payRefundOrder.setRefundMoney(rightsOrder.getRefundMoney());
        payRefundOrder.setRightsRefundStatus(RightsOrderConstant.RightsRefundStatus.WAIT);
        payRefundOrder.setRefundPoint(rightsOrder.getRefundPoint());
        payRefundOrderService.create(payRefundOrder);
        return payRefundOrder;
    }


    /**
     * 退款成功后的主订单或订单封单
     *
     * @param rightsOrder
     * @return
     */
    @Override
    public RightsOrder refundSuccessOperate(RightsOrder rightsOrder) {
        /**
         * 更新维权单的退款状态
         */
        rightsOrder.setRightsOperateStatus(RightsOrderConstant.RightsOperateStatus.REFUND_COMPLETE);
        rightsOrder.setRightsRefundStatus(RightsOrderConstant.RightsRefundStatus.SUCCESS);
        this.modify(rightsOrder);

        if (rightsOrder.getIsAllRights()) {
            orderService.refundOperate(rightsOrder.loadOrder());

        } else {
            List<RightsChildOrder> rightsChildOrders = rightsOrder.loadRightsChildOrders();
            rightsChildOrders.forEach(rightsChildOrder -> {
                if (rightsChildOrder.getChildOrder() != null) {
                    ChildOrder childOrder = childOrderService.refundOperate(rightsChildOrder.getChildOrder());

                    if (OrderConstant.OrderType.SALE_ORDER.equals(childOrder.getOrderType())) {
                        if (OrderConstant.ShipStatus.NO_SHIP.equals(childOrder.getShipStatus())) {
                            //自动入库记录一下
                            OrderStockTo to = new OrderStockTo();
                            to.setSingleGoodsId(childOrder.getSingleGoodsId());
                            to.setChangeStock(childOrder.getNumber());
                            to.setOrderId(childOrder.getOrderId());
                            to.setRightsCode(rightsOrder.getRightsCode());
                            to.setRightsChildId(rightsChildOrder.getId());
                            to.setRightsId(rightsChildOrder.getRightsId());
                            to.setChildReferId(childOrder.getId());
                            to.setGoodsTitle(childOrder.getGoodsTitle());
                            to.setOrderCode(childOrder.getOrderCode());
                            to.setSkuSetName(childOrder.getSkuSetName());
                            to.setUserMobile(childOrder.getMobile());
                            productSingleGoodsService.rightsChildOrderInStock(childOrder.getShopId(), to);

                            //自动入库记录一下
                            rightsChildOrder.setInStockNum(rightsChildOrder.getRefundNum());
                            rightsChildOrderService.modify(rightsChildOrder);
                        }
                    }


                    //同步把订单封单
                    childOrderService.endChildOrderSync(rightsChildOrder.getChildOrder());
                }
            });
        }

        if (rightsOrder.getRefundMoney().compareTo(BigDecimal.ZERO) > 0) {
            /**
             * 退款后入商家所得账单
             */
            shopOrderGainsService.refund(rightsOrder);
        }
        return rightsOrder;
    }

    /**
     * 买家申请维权，商家过期没有同意，需要自动同意的维权单
     * 条件
     * 1、刚刚申请
     * 2、待退款
     * 3、有最后同意时间
     * 4、当前时间过了同意的最后时间
     *
     * @return
     */
    @Override
    public List<RightsOrder> needAutoAgree() {
        return this.list(new LambdaQueryWrapper<RightsOrder>()
                .eq(RightsOrder::getRightsOperateStatus, RightsOrderConstant.RightsOperateStatus.APPLY.getCode())
                .eq(RightsOrder::getRightsRefundStatus, RightsOrderConstant.RightsRefundStatus.WAIT)
                .gt(RightsOrder::getLastAgreeTime, 0)
                .le(RightsOrder::getLastAgreeTime, System.currentTimeMillis())
                .eq(RightsOrder::getValid, true)
        );
    }

    /**
     * 商家同意之后，买家过期没有填写物流单，需要自动取消的维权单（退货单）
     * 条件
     * 1、退货退款维权单
     * 2、待退款
     * 3、商家同意退货退款
     * 4、有最后发货时间
     * 5、当前时间过了最后发货时间
     *
     * @return
     */
    @Override
    public List<RightsOrder> needAutoCancelRights() {
        return this.list(new LambdaQueryWrapper<RightsOrder>()
                .eq(RightsOrder::getRightsOperateStatus, RightsOrderConstant.RightsOperateStatus.AGREE.getCode())
                .eq(RightsOrder::getRightsType, OrderConstant.RightsType.RETURN)
                .eq(RightsOrder::getRightsRefundStatus, RightsOrderConstant.RightsRefundStatus.WAIT)
                .gt(RightsOrder::getLastShipTime, 0)
                .le(RightsOrder::getLastShipTime, System.currentTimeMillis())
                .eq(RightsOrder::getValid, true)
        );
    }

    /**
     * 需要自动收货的维权单（退货单）
     * 条件
     * 1、退货退款维权单
     * 2、待退款
     * 3、买家已发货
     * 4、有最后收货时间
     * 5、当前时间过了最后收货时间
     *
     * @return
     */
    @Override
    public List<RightsOrder> needAutoReceiptRights() {
        return this.list(new LambdaQueryWrapper<RightsOrder>()
                .eq(RightsOrder::getRightsOperateStatus, RightsOrderConstant.RightsOperateStatus.USER_SHIP.getCode())
                .eq(RightsOrder::getRightsRefundStatus, RightsOrderConstant.RightsRefundStatus.WAIT)
                .eq(RightsOrder::getRightsType, OrderConstant.RightsType.RETURN)
                .gt(RightsOrder::getLastReceiptTime, 0)
                .le(RightsOrder::getLastReceiptTime, System.currentTimeMillis())
                .eq(RightsOrder::getValid, true)
        );
    }


    @Override
    public RightsOrder loadByShopIdAndId(Long shopId, Long id, boolean tw) {
        RightsOrder one = this.getOne(new LambdaQueryWrapper<RightsOrder>()
                .eq(RightsOrder::getShopId, shopId)
                .eq(RightsOrder::getId, id)
                .last("limit 1"));

        if (one == null && tw) {
            // 抛异常 维权订单不存在
            throw new RRException(OrderException.RIGHTS_ORDER_NOT_EXISTS);
        }

        return one;
    }

    @Override
    public RightsOrder loadById(Long id, boolean tw) {
        RightsOrder one = this.getById(id);
        if (one == null && tw) {
            throw new RRException(OrderException.RIGHTS_ORDER_NOT_EXISTS);
        }

        return one;
    }

    /**
     * 创建日志
     *
     * @param rightsId
     * @param operateStatus
     * @param reason
     * @param VoucherImages
     * @param operatePerson
     * @return
     */
    private RightsOrderOperateRecord createRecord(Long rightsId,
                                                  RightsOrderConstant.RightsOperateStatus operateStatus,
                                                  String reason,
                                                  List<String> VoucherImages,
                                                  RightsOrderConstant.RightsOperatePerson operatePerson) {
        RightsOrderOperateRecord record = new RightsOrderOperateRecord();
        record.setRightsOrderId(rightsId);
        record.setRightsOperateStatus(operateStatus);
        record.setReason(reason);
        record.setVoucherImages(VoucherImages);
        record.setRightsOperatePerson(operatePerson);
        recordService.create(record);
        return record;
    }

    /**
     * 构建子维权单
     *
     * @param rightsOrder
     * @param childOrder
     * @param refundNum
     * @param refundMoney
     * @return
     */
    private RightsChildOrder build(RightsOrder rightsOrder, ChildOrder childOrder, int refundNum, BigDecimal refundMoney, BigDecimal refundPoint) {
        RightsChildOrder rightsChildOrder = new RightsChildOrder();
        rightsChildOrder.setRightsId(rightsOrder.getId());
        rightsChildOrder.setShopId(rightsOrder.getShopId());
        rightsChildOrder.setOrderId(rightsOrder.getOrderId());
        rightsChildOrder.setChildOrderId(childOrder.getId());
        rightsChildOrder.setRefundMoney(refundMoney);
        rightsChildOrder.setRefundNum(refundNum);
        rightsChildOrder.setGoodsId(childOrder.getGoodsId());
        rightsChildOrder.setGoodsTitle(childOrder.getGoodsTitle());
        rightsChildOrder.setGoodsImg(childOrder.getGoodsImg());
        rightsChildOrder.setSalePrice(childOrder.getSalePrice());
        rightsChildOrder.setSkuBarCode(childOrder.getSkuBarCode());
        rightsChildOrder.setSkuSetName(childOrder.getSkuSetName());
        rightsChildOrder.setSkuHashCode(childOrder.getSkuHashCode());
        rightsChildOrder.setSingleGoodsId(childOrder.getSingleGoodsId());
        rightsChildOrder.setRefundPoint(refundPoint);
        rightsChildOrder.setThirdSkuId(childOrder.getThirdSkuId());
        ShopGainsConstant.GoodsType goodsType = ShopGainsConstant.GoodsType.COMMON_GOODS;
        if (OrderConstant.OrderType.SERVICE_ORDER.equals(childOrder.getOrderType())) {
            goodsType = ShopGainsConstant.GoodsType.SERVICE_GOODS;
        }
        rightsChildOrder.setGoodsType(goodsType);
        return rightsChildOrder;
    }

    /**
     * 构建主维权单
     *
     * @param order
     * @param dto
     * @return
     */
    private RightsOrder build(Order order, ApplyOrderRightsDTO dto) {
        RightsOrder rightsOrder = new RightsOrder();
        rightsOrder.setRightsCode(OrderGen.generateOrderNo());
        rightsOrder.setRefundMoney(dto.getRefundMoney());
        rightsOrder.setRefundPoint(dto.getRefundPoint());
        rightsOrder.setReason(dto.getReason());
        rightsOrder.setCaption(dto.getCaption());
        rightsOrder.setVoucherImages(dto.getVoucherImages());
        rightsOrder.setRightsCargoStatus(RightsOrderConstant.RightsCargoStatus.getByCode(dto.getRightsCargoStatus()));
        rightsOrder.setRightsType(OrderConstant.RightsType.getByCode(dto.getRightsType()));
        rightsOrder.setRightsOperatePerson(RightsOrderConstant.RightsOperatePerson.getByCode(dto.getRightsOperatePerson()));
        rightsOrder.setShopId(order.getShopId());
        rightsOrder.setShopName(order.getShopName());
        rightsOrder.setOrderId(order.getId());
        rightsOrder.setOrderCode(order.getOrderCode());
        rightsOrder.setPayMode(order.getPayMode());
        rightsOrder.setUserId(order.getUserId());
        rightsOrder.setMobile(order.getMobile());
        rightsOrder.setReceiver("");
        rightsOrder.setReceiverMobile("");
        rightsOrder.setThird(order.getThird());
        if (OrderConstant.OrderType.SALE_ORDER.equals(order.getOrderType())) {
            if (OrderConstant.ShipmentMode.EXPRESS.equals(order.getShipmentMode())) {
                OrderReceipt orderReceipt = order.loadOrderReceipt();
                rightsOrder.setReceiver(orderReceipt.getReceiver());
                rightsOrder.setReceiverMobile(orderReceipt.getMobile());
            } else {
                OrderSelfTake orderSelfTake = order.loadOrderSelfTake();
                rightsOrder.setReceiver(orderSelfTake.getReceiver());
                rightsOrder.setReceiverMobile(orderSelfTake.getMobile());
            }
            rightsOrder.setOrderType(OrderConstant.OrderType.SALE_ORDER);
        } else {
            rightsOrder.setOrderType(OrderConstant.OrderType.SERVICE_ORDER);
            SaleServiceOrderContacts saleServiceOrderContacts = saleServiceOrderContactsService.loadByOrderId(rightsOrder.getOrderId());
            rightsOrder.setReceiver(saleServiceOrderContacts.getContacts());
            rightsOrder.setReceiverMobile(saleServiceOrderContacts.getMobile());
        }

        rightsOrder.setPayRefundId(0L);
        rightsOrder.setPayRefundCode("");
        rightsOrder.setThirdRefundCode("");

        SaleConfig config = saleConfigService.getConfig();
        Integer day = SaleConfig.defaultRightsDays;
        if (config != null) {
            if (OrderConstant.RightsType.REFUND.equals(rightsOrder.getRightsType())) {
                day = config.getApplyRefundAutoProcessDays();
            } else {
                day = config.getApplyReturnAutoProcessDays();
            }
        }
        long lastAgreeTime = OrderConstant.getTomorrowAndDayTimestamp(System.currentTimeMillis(), day);
        rightsOrder.setLastAgreeTime(lastAgreeTime);
        return rightsOrder;
    }


    /**
     * 内部调用，取消维权
     *
     * @param rightsOrder
     */
    private void cancel(RightsOrder rightsOrder) {
        Order order = orderService.loadByUserIdAndId(rightsOrder.getUserId(), rightsOrder.getOrderId(), false);
        if (order != null) {
            order.setRightsStatus(OrderConstant.RightsStatus.NO);
            order.setRightsType(OrderConstant.RightsType.NO);
            orderService.modify(order);
            List<RightsChildOrder> rightsChildOrders = rightsOrder.loadRightsChildOrders();
            for (RightsChildOrder rightsChildOrder : rightsChildOrders) {
                ChildOrder childOrder = rightsChildOrder.getChildOrder();
                //更新子订单的维权状态
                childOrder.setRightsStatus(OrderConstant.RightsStatus.NO);
                childOrder.setRightsType(OrderConstant.RightsType.NO);
                childOrderService.modify(childOrder);
            }
        }
    }

    /**
     * 查询子维权订单的数量
     *
     * @param orderId
     * @return
     */
    private Integer getCountRightsOrder(Long orderId, Boolean isMainOrder) {
        return this.baseMapper.selectCount(new LambdaQueryWrapper<RightsOrder>()
                .eq(RightsOrder::getOrderId, orderId)
                .eq(RightsOrder::getIsAllRights, isMainOrder)
                .eq(RightsOrder::getValid, true));
    }

    /**
     * 快钱退款脚本
     */
    @Override
    public R kqRefund() {
        // 查询数据库对账数据
        List<KqRefundDTO> list = this.baseMapper.getKqRefundInfo();

        List<String> kqSuccess = new ArrayList<>();
        List<String> kqFail = new ArrayList<>();
        List<String> kqOther = new ArrayList<>();
        List<String> kqQueryFail = new ArrayList<>();
        List<String> kqCatch = new ArrayList<>();

//        for (KqRefundDTO item : list) {
//
//            try {
//                Map<String, Object> map = InitQuery.gateWayInitQuery(item.getPayOrderCode());
//                log.info(JSONObject.toJSONString(map));
//
//                JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(map));
//
//                if ("1".equals(jsonObject.getString("resultCode"))) {
//
//                    // 请求成功
//                    if ("S".equals(jsonObject.getString("txnFlg"))) {
//
//                        // 订单支付成功
//                        kqSuccess.add(item.getPayOrderCode());
//                    } else if ("F".equals(jsonObject.getString("txnFlg"))) {
//
//                        // 订单支付失败
//                        kqFail.add(item.getPayOrderCode());
//
//                    } else {
//                        // 问题订单
//                        kqOther.add(item.getPayOrderCode());
//
//                    }
//
//                } else {
//                    // 请求失败订单
//                    kqQueryFail.add(item.getPayOrderCode());
//
//                }
//            } catch (Exception e) {
//                kqCatch.add(item.getPayOrderCode());
//            }
//
//        }
//
//        log.info("支付成功订单号：{}, 总数:{}", kqSuccess, kqSuccess.size());
//        log.info("支付失败订单号：{}, 总数:{}", kqFail, kqFail.size());
//        log.info("问题订单号：{}, 总数:{}", kqOther, kqOther.size());
//        log.info("请求失败订单号：{}, 总数:{}", kqQueryFail, kqQueryFail.size());
//        log.info("catch异常订单号：{}, 总数:{}", kqCatch, kqCatch.size());



        //----------------------------------------------


        for (KqRefundDTO item : list) {

            try {

                // 订单查询
                Map<String, Object> order = InitQuery.gateWayInitQuery(item.getPayOrderCode());

                JSONObject orderJS = JSONObject.parseObject(JSONObject.toJSONString(order));

                Map<String, Object> map = InitReFund.gateWayInitReFund(item.getAmount(),item.getPayOrderCode(),
                        orderJS.getString("idBizCtrl"), "127.0.0.1", "20240715-16异常退款");

                JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(map));

                log.info("快钱退款交易:{}", jsonObject.toJSONString());
                if ("1".equals(jsonObject.getString("resultCode"))) {

                    // 请求成功
                    if ("S".equals(jsonObject.getString("txnFlg"))) {

                        // 退款成功
                        kqSuccess.add(item.getPayOrderCode());
                    } else if ("F".equals(jsonObject.getString("txnFlg"))) {

                        // 退款失败
                        kqFail.add(item.getPayOrderCode());

                    } else {
                        // 问题订单
                        kqOther.add(item.getPayOrderCode());

                    }

                } else {
                    // 请求失败订单
                    kqQueryFail.add(item.getPayOrderCode());

                }


            } catch (Exception e) {
                kqCatch.add(item.getPayOrderCode());
            }


        }

        log.info("成功订单号：{}, 总数:{}", kqSuccess, kqSuccess.size());
        log.info("失败订单号：{}, 总数:{}", kqFail, kqFail.size());
        log.info("问题订单号：{}, 总数:{}", kqOther, kqOther.size());
        log.info("请求失败订单号：{}, 总数:{}", kqQueryFail, kqQueryFail.size());
        log.info("catch异常订单号：{}, 总数:{}", kqCatch, kqCatch.size());

        return R.ok();
    }


}
